Compare commits
262 Commits
Author | SHA1 | Date |
---|---|---|
Zeno Rogue | 7b3d2c2626 | |
Zeno Rogue | 126f45a714 | |
Jacob Mandelson | 11837d9614 | |
Zeno Rogue | 64569f1818 | |
Jacob Mandelson | cd2152ffad | |
Zeno Rogue | eee39b0340 | |
Zeno Rogue | 937c830571 | |
Zeno Rogue | 4ec627b1a1 | |
Zeno Rogue | 1a70e54e24 | |
Zeno Rogue | a70a9dc663 | |
Zeno Rogue | 879549ca5d | |
Zeno Rogue | 7982ea0e58 | |
Zeno Rogue | 7b99248c06 | |
Zeno Rogue | dc136cc937 | |
Jacob Mandelson | 3f78c11e6c | |
Jacob Mandelson | 1dd4da5135 | |
Jacob Mandelson | 601274e67a | |
Zeno Rogue | 7581ba887b | |
Zeno Rogue | 6b03aca3c0 | |
Zeno Rogue | 80df589bd2 | |
Zeno Rogue | 159b47e72a | |
Zeno Rogue | 9a33e63f53 | |
Zeno Rogue | 10184f9087 | |
Zeno Rogue | 6b0dd547bd | |
Zeno Rogue | 542e2520c1 | |
Zeno Rogue | f2d81746a7 | |
Zeno Rogue | a130fbbc50 | |
Zeno Rogue | 2097fde609 | |
Zeno Rogue | bc5e1d78c9 | |
Zeno Rogue | e324ae07f3 | |
Zeno Rogue | 215be1ea17 | |
Zeno Rogue | 53461e6c5a | |
Zeno Rogue | 7a81b6b0de | |
Zeno Rogue | 723422e137 | |
Zeno Rogue | 50881f519f | |
Zeno Rogue | df67249ec0 | |
Zeno Rogue | 0a9714e657 | |
Zeno Rogue | 5eb7cfc17a | |
Zeno Rogue | 000bfd4b97 | |
Zeno Rogue | 0b0ad4abe3 | |
Zeno Rogue | 305d546ae1 | |
Zeno Rogue | c369c08bc9 | |
Zeno Rogue | 52f9cc820b | |
Zeno Rogue | 4c81c0cc5d | |
Zeno Rogue | 51ecd882e1 | |
Zeno Rogue | 9ba9797068 | |
Zeno Rogue | ba972ea8d8 | |
Zeno Rogue | e4b0ebbd89 | |
Zeno Rogue | 35ddcf6fe1 | |
Zeno Rogue | 7c2aca91a4 | |
Zeno Rogue | 43702b82a1 | |
Zeno Rogue | 43a3e8f030 | |
Zeno Rogue | ce825db2c0 | |
Zeno Rogue | b8a7e6e093 | |
Zeno Rogue | 962efb3152 | |
Zeno Rogue | 84666ade8c | |
Zeno Rogue | 9aa15f96e1 | |
Zeno Rogue | bc22d17a16 | |
Zeno Rogue | d9a03ab1d3 | |
Zeno Rogue | 5ae3bc02d1 | |
Zeno Rogue | aafced83aa | |
Zeno Rogue | 33aacfa289 | |
Zeno Rogue | d074606cae | |
Zeno Rogue | 6aecf921bf | |
Zeno Rogue | fa99e83019 | |
Zeno Rogue | 1003808999 | |
Zeno Rogue | 5085853fb4 | |
Zeno Rogue | 9372ecb8f8 | |
Zeno Rogue | 690b2164db | |
Zeno Rogue | 16e3daeab5 | |
Zeno Rogue | 0a16e53561 | |
Zeno Rogue | 443be1acda | |
Zeno Rogue | ba9c41bed2 | |
Zeno Rogue | 329ad76c3c | |
Zeno Rogue | de20daf708 | |
Zeno Rogue | f229c489cd | |
Zeno Rogue | 1e3347590b | |
Zeno Rogue | fd1960191e | |
Zeno Rogue | 942fd9dafb | |
Zeno Rogue | f1e91a1614 | |
Zeno Rogue | e71ddf1140 | |
Zeno Rogue | a0ba84d70c | |
Zeno Rogue | 404b964f28 | |
Jacob Mandelson | b56d2d21bf | |
Zeno Rogue | 27fb2d92d7 | |
Zeno Rogue | ec9be47a83 | |
Jacob Mandelson | 14519dc258 | |
Jacob Mandelson | c3ef9c2733 | |
Jacob Mandelson | c29517b5b0 | |
Zeno Rogue | e91c11ffb7 | |
Zeno Rogue | 7d3d3a0869 | |
Tokarak | d0d4b24f91 | |
Tokarak | 2659d08b78 | |
Tokarak | 45db9977a0 | |
Tokarak | aa78aacdf3 | |
Tokarak | fd128d24c6 | |
Jacob Mandelson | d756224f8d | |
Zeno Rogue | fbea2d91ce | |
Zeno Rogue | d4f449d994 | |
Zeno Rogue | 9807b1b3ba | |
Zeno Rogue | 4d761385ac | |
Zeno Rogue | 05b6cdea3e | |
Zeno Rogue | 10646933db | |
Zeno Rogue | 521b452436 | |
Zeno Rogue | 0323e4100e | |
Zeno Rogue | 0708c0e2bc | |
Zeno Rogue | b7db56812e | |
Zeno Rogue | 7fc90f116b | |
Zeno Rogue | 824fa9a732 | |
Zeno Rogue | 92603dddcc | |
Zeno Rogue | 32d329d81e | |
Zeno Rogue | b9608dcd4c | |
Zeno Rogue | 977bd8ca9d | |
Zeno Rogue | 869c63cb88 | |
Zeno Rogue | 5377147b1a | |
Zeno Rogue | e83d38e267 | |
Zeno Rogue | 1fc02631c8 | |
Zeno Rogue | edff317759 | |
Jacob Mandelson | b8de8155da | |
Zeno Rogue | 9bc4e21f10 | |
Zeno Rogue | a328568ee5 | |
Zeno Rogue | 494fc4ec11 | |
Zeno Rogue | 6f7e5b4d6a | |
Zeno Rogue | ccea416237 | |
Zeno Rogue | 4a908273d0 | |
Zeno Rogue | 5efacd787d | |
Zeno Rogue | b07987b2f4 | |
Zeno Rogue | 84ada5184f | |
Zeno Rogue | 14b68f0b64 | |
Zeno Rogue | 960485ec8e | |
Zeno Rogue | e032e619c0 | |
Zeno Rogue | 57f6fb5f71 | |
Zeno Rogue | d2cd6fa2c1 | |
Zeno Rogue | 8a407f4505 | |
Zeno Rogue | 6abb82174e | |
Zeno Rogue | dea9fea67f | |
Zeno Rogue | d618b10889 | |
Zeno Rogue | d250abf1a4 | |
Zeno Rogue | 89563ebde9 | |
Zeno Rogue | 445c240c79 | |
Zeno Rogue | 15b711e099 | |
Zeno Rogue | 8002f42d71 | |
Zeno Rogue | 79f2940683 | |
Zeno Rogue | 0ec4e46bf0 | |
Zeno Rogue | c55550de57 | |
Zeno Rogue | 886a7ff43e | |
Zeno Rogue | deb207e4c3 | |
Zeno Rogue | 819d815d59 | |
Zeno Rogue | b20288557e | |
Zeno Rogue | 4a8eb08340 | |
Zeno Rogue | 007a111eab | |
Zeno Rogue | 65e9f68bc7 | |
Zeno Rogue | 3e30a7ded1 | |
Zeno Rogue | 5f8d250940 | |
Zeno Rogue | dee90f8d7c | |
Zeno Rogue | d43b19625e | |
Zeno Rogue | f32a2708b4 | |
Zeno Rogue | be27fc0fce | |
Zeno Rogue | 61720cec5e | |
Zeno Rogue | 7cf1643c5d | |
Zeno Rogue | 3791daf9e3 | |
Zeno Rogue | e9941d29d3 | |
Zeno Rogue | afd4a3f4e3 | |
Zeno Rogue | 66a79fe2cd | |
Zeno Rogue | 350963852c | |
Zeno Rogue | a650fe7faf | |
Zeno Rogue | fdf83820f2 | |
Zeno Rogue | 6b723977dd | |
Zeno Rogue | 1b3aecc10c | |
Zeno Rogue | e762da439c | |
Zeno Rogue | 7f023b2459 | |
Zeno Rogue | 2a9ae3071d | |
Zeno Rogue | de21375f40 | |
Zeno Rogue | 7bc2715a43 | |
Zeno Rogue | 04c15fc9c6 | |
Zeno Rogue | 9430c26970 | |
Zeno Rogue | 616607dc8e | |
Zeno Rogue | 86f5a040c9 | |
Zeno Rogue | 37b498203c | |
Zeno Rogue | 77a4bb4160 | |
Zeno Rogue | 5bdade94b6 | |
Zeno Rogue | 0b526cbdfb | |
Zeno Rogue | a82d9b2266 | |
Zeno Rogue | 0e018df878 | |
Zeno Rogue | 1c5709a3c9 | |
Zeno Rogue | c230e03a0a | |
Zeno Rogue | b71cd1e44d | |
Zeno Rogue | ef936d7b0e | |
Zeno Rogue | 97f8c5ed72 | |
Zeno Rogue | 94bf06f7dc | |
Zeno Rogue | 261800d765 | |
Zeno Rogue | 2b2cc4e8a9 | |
Zeno Rogue | cbccf4936d | |
Zeno Rogue | 68f5ad6e92 | |
Zeno Rogue | 9f44f98b0a | |
Zeno Rogue | 5bb4b69c23 | |
Zeno Rogue | 9cc370a2d2 | |
Zeno Rogue | 26e61783b2 | |
Zeno Rogue | d0d354b53a | |
Zeno Rogue | 78a1615c6c | |
Zeno Rogue | 125b271889 | |
Zeno Rogue | c85b4d2f2b | |
Zeno Rogue | 424186b10d | |
Zeno Rogue | 4421143ae5 | |
Jacob Mandelson | ee293310b6 | |
Jacob Mandelson | a40e72f1d8 | |
Jacob Mandelson | 3bd67f466a | |
Zeno Rogue | ddb9fbd58e | |
Zeno Rogue | b152bac377 | |
Jacob Mandelson | a626ede2bf | |
Jacob Mandelson | 1f2692a4fb | |
Jacob Mandelson | e31c9dc263 | |
Jacob Mandelson | 7d04b0c717 | |
Jacob Mandelson | 0f84812d15 | |
Jacob Mandelson | 80f90dec52 | |
Zeno Rogue | e840e39ba0 | |
Zeno Rogue | fa9c2da41d | |
Zeno Rogue | f291bbb1d1 | |
Zeno Rogue | 2de61962f9 | |
Zeno Rogue | 43fc692b47 | |
Zeno Rogue | 87ac19febe | |
Zeno Rogue | 2379228ab4 | |
Zeno Rogue | 5aac5fd2a3 | |
Zeno Rogue | 46eaee44ef | |
Zeno Rogue | 21d3f8bec4 | |
Zeno Rogue | c2d06dc05b | |
Zeno Rogue | 21a782cd28 | |
Zeno Rogue | bf512e39ce | |
Zeno Rogue | de5ddc3034 | |
Zeno Rogue | b4b00baa5e | |
Zeno Rogue | 648dd67dc7 | |
Zeno Rogue | 30f6fbc16c | |
Zeno Rogue | 00b5fe3a22 | |
Zeno Rogue | 55493cc364 | |
Zeno Rogue | 3b1918535f | |
Zeno Rogue | 650108bad3 | |
Zeno Rogue | 79e74e8d53 | |
Zeno Rogue | 3ed43b8c7d | |
Zeno Rogue | 5508fb7183 | |
Zeno Rogue | 6c682510bc | |
Zeno Rogue | 6d9f7e791b | |
Zeno Rogue | e343ed9c3f | |
Zeno Rogue | 8af2a43f5e | |
Zeno Rogue | e33f26d51f | |
Zeno Rogue | 60980bcb8b | |
Zeno Rogue | bcc026173e | |
Zeno Rogue | d86f70886d | |
Zeno Rogue | 2a7e2e96ca | |
Zeno Rogue | a91f74c86c | |
Zeno Rogue | 285c71e10f | |
Zeno Rogue | a28c62416f | |
Zeno Rogue | bfd1945d7b | |
Zeno Rogue | f271ba6b4d | |
Zeno Rogue | f87a7c5f1c | |
Zeno Rogue | 9ce5c63708 | |
Jacob Mandelson | 56c8838101 | |
Zeno Rogue | 9a590ecc42 | |
Zeno Rogue | eb1488b24f | |
Zeno Rogue | 26328f5493 | |
Zeno Rogue | 52081a916a | |
Jacob Mandelson | 08a774dfd4 | |
Jacob Mandelson | acd88377a9 |
|
@ -1,68 +0,0 @@
|
|||
name: Github CI on Android
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
branches: [master]
|
||||
|
||||
jobs:
|
||||
android_build:
|
||||
name: Test build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Validate gradle-wrapper.jar
|
||||
uses: gradle/wrapper-validation-action@v1
|
||||
- name: Install build dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get -y install gcc libsdl1.2-dev libsdl-ttf2.0-dev libsdl-gfx1.2-dev libsdl-mixer1.2-dev libglew-dev libpng-dev
|
||||
- name: Build
|
||||
run: |
|
||||
cd hyperroid
|
||||
./copy.sh
|
||||
./gradlew assembleDebug
|
||||
- name: Upload APK
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: hyperroid_debug
|
||||
path: hyperroid/app/build/outputs/apk/debug/app-debug.apk
|
||||
|
||||
android_test:
|
||||
needs: android_build
|
||||
name: Test-run in emulator
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- name: Download APK
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: hyperroid_debug
|
||||
- name: Create a helper wait script
|
||||
run: |
|
||||
cat > wait-for-load.sh << ENDOFSCRIPT
|
||||
#!/bin/sh
|
||||
while ! adb logcat -d "HyperRogue:V" "*:S" | grep "Game initialized"
|
||||
do
|
||||
sleep 2
|
||||
done
|
||||
ENDOFSCRIPT
|
||||
chmod u+x wait-for-load.sh
|
||||
- name: Run in emulator
|
||||
uses: ReactiveCircus/android-emulator-runner@v2.11.1
|
||||
with:
|
||||
api-level: 28
|
||||
emulator-options: -no-window -gpu swiftshader_indirect -no-snapshot -no-snapstorage -noaudio -no-boot-anim -skin 1440x2560
|
||||
script: |
|
||||
adb wait-for-device
|
||||
adb install -t app-debug.apk
|
||||
adb shell am start -W -n com.roguetemple.hyperroid/com.roguetemple.hyperroid.HyperRogue
|
||||
./wait-for-load.sh
|
||||
adb shell input keyevent 41 # send "M" keypress to display main menu
|
||||
adb shell screencap /sdcard/hyperroid.png
|
||||
adb pull /sdcard/hyperroid.png
|
||||
- name: Upload screenshot
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: screenshot
|
||||
path: hyperroid.png
|
|
@ -13,7 +13,9 @@ jobs:
|
|||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, macos-latest]
|
||||
# os: [ubuntu-latest, macos-latest]
|
||||
# macos is broken for now
|
||||
os: [ubuntu-latest]
|
||||
compiler: [gcc, clang]
|
||||
build_system: [makefile, mymake]
|
||||
hyper_use_rviz: [rviz_1, rviz_0]
|
||||
|
@ -71,13 +73,15 @@ jobs:
|
|||
- name: Do a simple test
|
||||
run: .github/workflows/test_simple.sh
|
||||
|
||||
emscripten:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Build
|
||||
run: |
|
||||
docker run --rm -v $(pwd):/src trzeci/emscripten make emscripten
|
||||
- name: Do a simple test
|
||||
run: |
|
||||
ls -lAF hyper.html hyper.js hyper.wasm
|
||||
# broken for now
|
||||
|
||||
# emscripten:
|
||||
# runs-on: ubuntu-latest
|
||||
# steps:
|
||||
# - uses: actions/checkout@v2
|
||||
# - name: Build
|
||||
# run: |
|
||||
# docker run --rm -v $(pwd):/src trzeci/emscripten make emscripten
|
||||
# - name: Do a simple test
|
||||
# run: |
|
||||
# ls -lAF hyper.html hyper.js hyper.wasm
|
||||
|
|
|
@ -9,7 +9,9 @@ cat << ENDOFCMDS > .github/workflows/gdb_cmds.txt
|
|||
exit 1
|
||||
ENDOFCMDS
|
||||
|
||||
gdb --batch -x .github/workflows/gdb_cmds.txt ./hyperrogue
|
||||
echo not running gdb -- not working currently
|
||||
echo gdb --batch -x .github/workflows/gdb_cmds.txt ./hyperrogue
|
||||
|
||||
else
|
||||
./hyperrogue --version
|
||||
fi
|
||||
|
|
193
.travis.yml
193
.travis.yml
|
@ -1,193 +0,0 @@
|
|||
language: cpp
|
||||
dist: bionic
|
||||
services:
|
||||
- docker
|
||||
matrix:
|
||||
include:
|
||||
- os: linux # Linux GCC, make
|
||||
compiler: gcc
|
||||
env: >-
|
||||
TRAVIS_OS_NAME=linux
|
||||
TRAVIS_COMPILER_NAME=gcc
|
||||
TRAVIS_BUILD_SYSTEM=Makefile
|
||||
HYPERROGUE_USE_GLEW=1
|
||||
HYPERROGUE_USE_PNG=1
|
||||
- os: linux # Linux GCC, make, no libpng
|
||||
compiler: gcc
|
||||
env: >-
|
||||
TRAVIS_OS_NAME=linux
|
||||
TRAVIS_COMPILER_NAME=gcc
|
||||
TRAVIS_BUILD_SYSTEM=Makefile
|
||||
HYPERROGUE_USE_GLEW=1
|
||||
HYPERROGUE_USE_PNG=0
|
||||
- os: linux # Linux GCC, make, Rogueviz
|
||||
compiler: gcc
|
||||
env: >-
|
||||
TRAVIS_OS_NAME=linux
|
||||
TRAVIS_COMPILER_NAME=gcc
|
||||
TRAVIS_BUILD_SYSTEM=Makefile
|
||||
HYPERROGUE_USE_GLEW=1
|
||||
HYPERROGUE_USE_PNG=1
|
||||
HYPERROGUE_USE_ROGUEVIZ=1
|
||||
- os: linux # Linux Clang, make
|
||||
compiler: clang
|
||||
env: >-
|
||||
TRAVIS_OS_NAME=linux
|
||||
TRAVIS_COMPILER_NAME=clang
|
||||
TRAVIS_BUILD_SYSTEM=Makefile
|
||||
HYPERROGUE_USE_GLEW=1
|
||||
HYPERROGUE_USE_PNG=1
|
||||
- os: linux # Linux Clang, make, Rogueviz
|
||||
compiler: clang
|
||||
env: >-
|
||||
TRAVIS_OS_NAME=linux
|
||||
TRAVIS_COMPILER_NAME=clang
|
||||
TRAVIS_BUILD_SYSTEM=Makefile
|
||||
HYPERROGUE_USE_GLEW=1
|
||||
HYPERROGUE_USE_PNG=1
|
||||
HYPERROGUE_USE_ROGUEVIZ=1
|
||||
- os: osx # OSX, make
|
||||
osx_image: xcode12u
|
||||
compiler: clang
|
||||
env: >-
|
||||
TRAVIS_OS_NAME=osx
|
||||
TRAVIS_COMPILER_NAME=clang
|
||||
TRAVIS_BUILD_SYSTEM=Makefile
|
||||
HYPERROGUE_USE_GLEW=1
|
||||
HYPERROGUE_USE_PNG=1
|
||||
- os: osx # OSX, make, no libpng
|
||||
osx_image: xcode11.6
|
||||
compiler: clang
|
||||
env: >-
|
||||
TRAVIS_OS_NAME=osx
|
||||
TRAVIS_COMPILER_NAME=clang
|
||||
TRAVIS_BUILD_SYSTEM=Makefile
|
||||
HYPERROGUE_USE_GLEW=1
|
||||
HYPERROGUE_USE_PNG=0
|
||||
- os: osx # OSX, make, Rogueviz
|
||||
osx_image: xcode11.5
|
||||
compiler: clang
|
||||
env: >-
|
||||
TRAVIS_OS_NAME=osx
|
||||
TRAVIS_COMPILER_NAME=clang
|
||||
TRAVIS_BUILD_SYSTEM=Makefile
|
||||
HYPERROGUE_USE_GLEW=1
|
||||
HYPERROGUE_USE_PNG=1
|
||||
HYPERROGUE_USE_ROGUEVIZ=1
|
||||
- os: linux # Linux GCC, mymake
|
||||
compiler: gcc
|
||||
env: >-
|
||||
TRAVIS_OS_NAME=linux
|
||||
TRAVIS_COMPILER_NAME=gcc
|
||||
TRAVIS_BUILD_SYSTEM=mymake
|
||||
HYPERROGUE_USE_GLEW=1
|
||||
HYPERROGUE_USE_PNG=1
|
||||
- os: linux # Linux GCC, mymake, Rogueviz
|
||||
compiler: gcc
|
||||
env: >-
|
||||
TRAVIS_OS_NAME=linux
|
||||
TRAVIS_COMPILER_NAME=gcc
|
||||
TRAVIS_BUILD_SYSTEM=mymake
|
||||
HYPERROGUE_USE_GLEW=1
|
||||
HYPERROGUE_USE_PNG=1
|
||||
HYPERROGUE_USE_ROGUEVIZ=1
|
||||
- os: osx # OSX, mymake
|
||||
osx_image: xcode11.4
|
||||
compiler: clang
|
||||
env: >-
|
||||
TRAVIS_OS_NAME=osx
|
||||
TRAVIS_COMPILER_NAME=clang
|
||||
TRAVIS_BUILD_SYSTEM=mymake
|
||||
HYPERROGUE_USE_GLEW=1
|
||||
HYPERROGUE_USE_PNG=1
|
||||
- os: osx # OSX, mymake, Rogueviz
|
||||
osx_image: xcode11.3
|
||||
compiler: clang
|
||||
env: >-
|
||||
TRAVIS_OS_NAME=osx
|
||||
TRAVIS_COMPILER_NAME=clang
|
||||
TRAVIS_BUILD_SYSTEM=mymake
|
||||
HYPERROGUE_USE_GLEW=1
|
||||
HYPERROGUE_USE_PNG=1
|
||||
HYPERROGUE_USE_ROGUEVIZ=1
|
||||
- os: linux # Emscripten
|
||||
env: >-
|
||||
TRAVIS_OS_NAME=linux
|
||||
TRAVIS_COMPILER_NAME=emscripten
|
||||
TRAVIS_BUILD_SYSTEM=emscripten
|
||||
|
||||
before_install:
|
||||
- |-
|
||||
# Install SDL
|
||||
if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then
|
||||
sudo apt-get update -qq
|
||||
sudo apt-get install -qq libsdl1.2-dev libsdl-gfx1.2-dev libsdl-mixer1.2-dev libsdl-ttf2.0-dev
|
||||
elif [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
|
||||
brew update
|
||||
brew install sdl sdl_gfx sdl_mixer sdl_ttf
|
||||
# work around https://stackoverflow.com/questions/51034399/ for now
|
||||
(cd /usr/local/include && ln -sf SDL/SDL.h)
|
||||
else
|
||||
exit 'Unsupported OS'
|
||||
fi
|
||||
- |-
|
||||
# Install GLEW if asked for
|
||||
if [[ "$HYPERROGUE_USE_GLEW" == "1" ]]; then
|
||||
if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then
|
||||
sudo apt-get install -qq libglew-dev
|
||||
elif [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
|
||||
brew install glew
|
||||
else
|
||||
exit 'Unsupported OS'
|
||||
fi
|
||||
fi
|
||||
- |-
|
||||
# Install libpng if asked for
|
||||
if [[ "$HYPERROGUE_USE_PNG" == "1" ]]; then
|
||||
if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then
|
||||
echo 'libpng is installed by default'
|
||||
elif [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
|
||||
brew install libpng
|
||||
else
|
||||
exit 'Unsupported OS'
|
||||
fi
|
||||
fi
|
||||
|
||||
script:
|
||||
- |-
|
||||
make clean
|
||||
if [[ "$(git status --porcelain)" ]]; then
|
||||
git status
|
||||
exit 'A build artifact was committed; git rm it and try again'
|
||||
fi
|
||||
- |-
|
||||
# Build hyperrogue.
|
||||
export CXXFLAGS_EARLY=-Werror
|
||||
if [[ "$TRAVIS_BUILD_SYSTEM" == "Makefile" ]]; then
|
||||
make
|
||||
elif [[ "$TRAVIS_BUILD_SYSTEM" == "mymake" ]]; then
|
||||
make mymake
|
||||
if [[ "$HYPERROGUE_USE_ROGUEVIZ" == "1" ]]; then
|
||||
./mymake -rv
|
||||
else
|
||||
./mymake
|
||||
fi
|
||||
mv hyper hyperrogue
|
||||
elif [[ "$TRAVIS_BUILD_SYSTEM" == "emscripten" ]]; then
|
||||
docker run --rm -v $(pwd):/src trzeci/emscripten make emscripten
|
||||
else
|
||||
exit 'Unsupported build system'
|
||||
fi
|
||||
- |-
|
||||
# Test hyperrogue.
|
||||
if [[ "$TRAVIS_BUILD_SYSTEM" == "emscripten" ]]; then
|
||||
ls -lAF hyper.html hyper.js hyper.wasm
|
||||
else
|
||||
./hyperrogue --help
|
||||
fi
|
||||
- |-
|
||||
make clean
|
||||
if [[ "$(git status --porcelain)" ]]; then
|
||||
git status
|
||||
exit 'make clean did not return the repository to its pre-build state'
|
||||
fi
|
39
Makefile
39
Makefile
|
@ -1,16 +1,24 @@
|
|||
# This Makefile works for Mac OS X (El Capitan), MinGW, and Linux.
|
||||
#
|
||||
# Environmental vairables:
|
||||
# If you want to build with Glew, set
|
||||
# HYPERROGUE_USE_GLEW=1
|
||||
# If you want to use libpng, set
|
||||
# HYPERROGUE_USE_PNG=1
|
||||
#
|
||||
# For Mac OS X:
|
||||
# Run "brew install sdl" to install SDL in /usr/local.
|
||||
# Run "brew install sdl_gfx".
|
||||
# Run "brew install sdl_mixer".
|
||||
# Run "brew install sdl_ttf".
|
||||
# Run "make" to build HyperRogue as ./hyperrogue.
|
||||
# Run `brew install sdl12-compat sdl_gfx sdl_mixer sdl_ttf`
|
||||
# Run `brew install glew libpng` to install the optional dependencies
|
||||
# Run `make` to build HyperRogue as `./hyperrogue`.
|
||||
#
|
||||
# For MSYS2 and MinGW-w64:
|
||||
# You might need to run commands such as "pacman -S mingw-w64-x86_64-SDL"
|
||||
# to install SDL and other required libraries.
|
||||
# Run "make" to build HyperRogue as ./hyperrogue.exe.
|
||||
# To install SDL and other required libraries, run these commands
|
||||
# from the MSYS2 shell:
|
||||
# pacman -S mingw-w64-ucrt-x86_64-gcc mingw-w64-ucrt-x86_64-glew
|
||||
# pacman -S mingw-w64-ucrt-x86_64-SDL mingw-w64-ucrt-x86_64-SDL_mixer
|
||||
# pacman -S mingw-w64-ucrt-x86_64-SDL_ttf mingw-w64-ucrt-x86_64-SDL_gfx
|
||||
# pacman -S make
|
||||
# Then run "make" to build HyperRogue as ./hyperrogue.exe.
|
||||
#
|
||||
# For Ubuntu Linux:
|
||||
# Run "sudo apt-get install libsdl-dev" to install SDL in /usr/local.
|
||||
|
@ -54,7 +62,7 @@ ifeq (${OS},linux)
|
|||
endif
|
||||
|
||||
ifeq (${OS},mingw)
|
||||
CXXFLAGS_EARLY += -DWINDOWS -mwindows -D_A_VOLID=8
|
||||
CXXFLAGS_EARLY += -DWINDOWS -mwindows -D_A_VOLID=8 -I/ucrt64/include/SDL
|
||||
EXE_EXTENSION := .exe
|
||||
LDFLAGS_GL := -lopengl32
|
||||
LDFLAGS_GLEW := -lglew32
|
||||
|
@ -68,9 +76,10 @@ ifeq (${OS},mingw)
|
|||
endif
|
||||
|
||||
ifeq (${OS},osx)
|
||||
CXXFLAGS_EARLY += -DMAC -I/usr/local/include
|
||||
HOMEBREW_PREFIX := $(shell brew --prefix)
|
||||
CXXFLAGS_EARLY += -DMAC -I$(HOMEBREW_PREFIX)/include -I$(HOMEBREW_PREFIX)/include/SDL
|
||||
EXE_EXTENSION :=
|
||||
LDFLAGS_EARLY += -L/usr/local/lib
|
||||
LDFLAGS_EARLY += -L$(HOMEBREW_PREFIX)/lib
|
||||
LDFLAGS_GL := -framework AppKit -framework OpenGL
|
||||
LDFLAGS_GLEW := -lGLEW
|
||||
LDFLAGS_PNG := -lpng
|
||||
|
@ -80,7 +89,7 @@ ifeq (${OS},osx)
|
|||
endif
|
||||
|
||||
ifeq (${TOOLCHAIN},clang)
|
||||
CXXFLAGS_STD = -std=c++11
|
||||
CXXFLAGS_STD = -std=c++14
|
||||
CXXFLAGS_EARLY += -fPIC
|
||||
CXXFLAGS_EARLY += -W -Wall -Wextra -Wsuggest-override -pedantic
|
||||
CXXFLAGS_EARLY += -Wno-unused-parameter -Wno-implicit-fallthrough -Wno-maybe-uninitialized -Wno-char-subscripts -Wno-unknown-warning-option
|
||||
|
@ -88,7 +97,7 @@ ifeq (${TOOLCHAIN},clang)
|
|||
endif
|
||||
|
||||
ifeq (${TOOLCHAIN},gcc)
|
||||
CXXFLAGS_STD = -std=c++11
|
||||
CXXFLAGS_STD = -std=c++14
|
||||
CXXFLAGS_EARLY += -fPIC
|
||||
CXXFLAGS_EARLY += -W -Wall -Wextra -pedantic
|
||||
CXXFLAGS_EARLY += -Wno-unused-parameter -Wno-implicit-fallthrough -Wno-maybe-uninitialized
|
||||
|
@ -96,7 +105,7 @@ ifeq (${TOOLCHAIN},gcc)
|
|||
endif
|
||||
|
||||
ifeq (${TOOLCHAIN},mingw)
|
||||
CXXFLAGS_STD = -std=c++11
|
||||
CXXFLAGS_STD = -std=c++14
|
||||
CXXFLAGS_EARLY += -W -Wall -Wextra
|
||||
CXXFLAGS_EARLY += -Wno-unused-parameter -Wno-implicit-fallthrough -Wno-maybe-uninitialized
|
||||
CXXFLAGS_EARLY += -Wno-invalid-offsetof
|
||||
|
@ -173,7 +182,7 @@ mymake$(EXE_EXTENSION): mymake.cpp
|
|||
emscripten: hyper.html
|
||||
|
||||
%.html %.js %.wasm: %.emscripten-sources
|
||||
emcc -std=c++11 -O3 -s USE_ZLIB=1 -s LEGACY_GL_EMULATION=1 -s TOTAL_MEMORY=128MB hyperweb.cpp -o hyper.html
|
||||
emcc -std=c++14 -O3 -s USE_ZLIB=1 -s LEGACY_GL_EMULATION=1 -s TOTAL_MEMORY=128MB hyperweb.cpp -o hyper.html
|
||||
|
||||
hyper.emscripten-sources: *.cpp autohdr.h
|
||||
|
||||
|
|
16
README.md
16
README.md
|
@ -1,11 +1,4 @@
|
|||
# HyperRogue
|
||||
<p>
|
||||
<a href="https://travis-ci.org/zenorogue/hyperrogue/builds">
|
||||
<img src="https://badges.herokuapp.com/travis/zenorogue/hyperrogue?branch=master&env=TRAVIS_BUILD_SYSTEM=Makefile&label=make" alt="TravisCI badge">
|
||||
<img src="https://badges.herokuapp.com/travis/zenorogue/hyperrogue?branch=master&env=TRAVIS_BUILD_SYSTEM=mymake&label=mymake" alt="TravisCI badge">
|
||||
<img src="https://badges.herokuapp.com/travis/zenorogue/hyperrogue?branch=master&env=TRAVIS_BUILD_SYSTEM=emscripten&label=web" alt="TravisCI badge">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
A puzzle roguelike in the hyperbolic plane. See the [HyperRogue website](http://roguetemple.com/z/hyper.php) for detailed and most up-to-date information.
|
||||
Compiled executables can be downloaded from [itch.io](https://zenorogue.itch.io/hyperrogue) and from the [HyperRogue website](http://www.roguetemple.com/z/hyper/download.php).
|
||||
|
@ -62,15 +55,13 @@ On Linux with apt-get:
|
|||
|
||||
On macOS with Homebrew:
|
||||
|
||||
```brew install sdl sdl_ttf sdl_gfx sdl_mixer glew```
|
||||
|
||||
macOS users might also have to edit /usr/local/include/SDL/SDL_gfxPrimitives.h at line 38 to use quote include.
|
||||
```brew install sdl sdl_ttf sdl_gfx sdl_mixer glew libpng```
|
||||
|
||||
### Building HyperRogue from source ###
|
||||
```
|
||||
git clone https://github.com/zenorogue/hyperrogue.git hyperrogue
|
||||
cd hyperrogue
|
||||
make
|
||||
HYPERROGUE_USE_GLEW=1 HYPERROGUE_USE_PNG=1 make
|
||||
```
|
||||
|
||||
The `mymake` program builds HyperRogue in parts. It takes longer than the method shown above, but it uses significantly less memory during compilation, and when you change something, `mymake` will only recompile the changed file.
|
||||
|
@ -83,3 +74,6 @@ make mymake && ./mymake
|
|||
```
|
||||
|
||||
The source code is not documented very well. You can see the current state of the documentation, as generated by Doxygen, [here](https://zenorogue.github.io/hyperrogue-doc/).
|
||||
|
||||
## Discussion ##
|
||||
The best place to discuss HyperRogue is our [Discord server|https://discord.com/invite/8G44XkR].
|
||||
|
|
|
@ -10,7 +10,9 @@
|
|||
#include "hyper.h"
|
||||
namespace hr {
|
||||
|
||||
#if HDR
|
||||
#define NUMLEADER 90
|
||||
#endif
|
||||
|
||||
EX bool test_achievements = false;
|
||||
|
||||
|
@ -86,9 +88,27 @@ EX const char* leadernames[NUMLEADER] = {
|
|||
"Crossbow (geometric)", // 89
|
||||
};
|
||||
|
||||
#if HDR
|
||||
#define LB_PRINCESS 36
|
||||
#define LB_STATISTICS 62
|
||||
#define LB_HALLOWEEN 63
|
||||
#define LB_HALLOWEEN 63
|
||||
#define LB_YENDOR_CHALLENGE 40
|
||||
#define LB_PURE_TACTICS 41
|
||||
#define LB_PURE_TACTICS_SHMUP 49
|
||||
#define LB_PURE_TACTICS_COOP 50
|
||||
#define LB_RACING 81
|
||||
#endif
|
||||
|
||||
EX void achievement_init();
|
||||
EX string myname();
|
||||
EX void achievement_close();
|
||||
EX void achievement_pump();
|
||||
|
||||
/** gain the given achievement.
|
||||
* @param s name of the achievement, e.g., DIAMOND1
|
||||
* @param flags one of the constants from namespace rg. The achievement is only awarded if special modes are matched exactly.
|
||||
*/
|
||||
EX void achievement_gain(const char* s, char flags IS(0));
|
||||
|
||||
EX bool haveLeaderboard(int id);
|
||||
EX int get_currentscore(int id);
|
||||
|
@ -96,7 +116,7 @@ EX void set_priority_board(int id);
|
|||
EX int get_sync_status();
|
||||
EX bool score_loaded(int id);
|
||||
EX int score_default(int id);
|
||||
|
||||
EX void improveItemScores();
|
||||
EX void upload_score(int id, int v);
|
||||
|
||||
string achievementMessage[3];
|
||||
|
@ -119,6 +139,7 @@ EX bool wrongMode(char flags) {
|
|||
if(disksize) return true;
|
||||
}
|
||||
if(ineligible_starting_land && !flags) return true;
|
||||
if(use_custom_land_list) return true;
|
||||
|
||||
if(shmup::on != (flags == rg::shmup || flags == rg::racing)) return true;
|
||||
if(racing::on != (flags == rg::racing)) return true;
|
||||
|
@ -144,6 +165,7 @@ EX bool wrongMode(char flags) {
|
|||
dls = land_structure;
|
||||
|
||||
if(land_structure != dls) return true;
|
||||
if(shmup::on && vid.creature_scale != 1) return true;
|
||||
if(numplayers() > 1 && !multi::friendly_fire) return true;
|
||||
if(numplayers() > 1 && multi::pvp_mode) return true;
|
||||
if(numplayers() > 1 && multi::split_screen) return true;
|
||||
|
@ -166,7 +188,7 @@ EX void achievement_gain_once(const string& s, char flags IS(0)) {
|
|||
|
||||
namespace rg {
|
||||
char check(bool b, char val = special_geometry) { return b ? val : fail; }
|
||||
};
|
||||
}
|
||||
|
||||
EX char specgeom_zebra() { return rg::check(geometry == gZebraQuotient && !disksize && BITRUNCATED && firstland == laDesert); }
|
||||
EX char specgeom_lovasz() { return rg::check(geometry == gKleinQuartic && variation == eVariation::untruncated && gp::param == gp::loc(1,1) && !disksize && in_lovasz()); }
|
||||
|
@ -217,29 +239,24 @@ EX void achievement_log(const char* s, char flags) {
|
|||
#endif
|
||||
}
|
||||
|
||||
EX void achievement_init();
|
||||
EX string myname();
|
||||
EX void achievement_close();
|
||||
#ifndef LEADER
|
||||
#define LEADER "Unknown"
|
||||
#define LEADERFULL "Unknown"
|
||||
#endif
|
||||
|
||||
/** gain the given achievement.
|
||||
* @param s name of the achievement, e.g., DIAMOND1
|
||||
* @param flags one of the constants from namespace rg. The achievement is only awarded if special modes are matched exactly.
|
||||
*/
|
||||
EX void achievement_gain(const char* s, char flags IS(0));
|
||||
|
||||
#if ISSTEAM
|
||||
void improveItemScores();
|
||||
#include "private/hypersteam.cpp"
|
||||
#elif !ISANDROID && !ISIOS
|
||||
#if !CAP_ACHIEVE
|
||||
void achievement_init() {}
|
||||
string myname() { return "Rogue"; }
|
||||
void achievement_close() {}
|
||||
// gain the achievement with the given name.
|
||||
// flags: 'e' - for Euclidean, 's' - for Shmup, '7' - for heptagonal
|
||||
// Only awarded if special modes are matched exactly.
|
||||
void achievement_gain(const char* s, char flags IS(0)) {
|
||||
void achievement_gain(const char* s, char flags) {
|
||||
achievement_log(s, flags);
|
||||
}
|
||||
void achievement_pump() {}
|
||||
EX int get_sync_status() { return 0; }
|
||||
EX void set_priority_board(int) { }
|
||||
#endif
|
||||
|
||||
// gain the achievement for collecting a number of 'it'.
|
||||
|
@ -644,7 +661,7 @@ int specific_what = 0;
|
|||
EX void improve_score(int i, eItem what) {
|
||||
if(offlineMode) return;
|
||||
LATE( improve_score(i, what); )
|
||||
#ifdef HAVE_ACHIEVEMENTS
|
||||
#if CAP_ACHIEVE
|
||||
if(haveLeaderboard(i)) updateHi(what, get_currentscore(i));
|
||||
if(items[what] && haveLeaderboard(i)) {
|
||||
if(items[what] > get_currentscore(i) && score_loaded(i)) {
|
||||
|
@ -658,7 +675,7 @@ EX void improve_score(int i, eItem what) {
|
|||
// scores for special challenges
|
||||
EX void achievement_score(int cat, int number) {
|
||||
if(offlineMode) return;
|
||||
#ifdef HAVE_ACHIEVEMENTS
|
||||
#if CAP_ACHIEVE
|
||||
if(cheater) return;
|
||||
if(casual) return;
|
||||
LATE( achievement_score(cat, number); )
|
||||
|
@ -680,6 +697,7 @@ EX void achievement_score(int cat, int number) {
|
|||
return;
|
||||
if(racing::on && cat != LB_RACING) return;
|
||||
if(bow::weapon) return;
|
||||
if(use_custom_land_list) return;
|
||||
upload_score(cat, number);
|
||||
#endif
|
||||
}
|
||||
|
@ -763,7 +781,7 @@ EX void achievement_final(bool really_final) {
|
|||
|
||||
LATE( achievement_final(really_final); )
|
||||
|
||||
#ifdef HAVE_ACHIEVEMENTS
|
||||
#if CAP_ACHIEVE
|
||||
if(ticks > next_stat_tick) {
|
||||
upload_score(LB_STATISTICS, time(NULL));
|
||||
next_stat_tick = ticks + 600000;
|
||||
|
@ -804,6 +822,7 @@ EX void achievement_final(bool really_final) {
|
|||
if(bow::crossbow_mode() && bow::style == bow::cbBull) specialcode += 32;
|
||||
if(bow::crossbow_mode() && bow::style == bow::cbGeodesic) specialcode += 64;
|
||||
if(bow::crossbow_mode() && bow::style == bow::cbGeometric) specialcode += 96;
|
||||
if(shmup::on && vid.creature_scale != 1) return;
|
||||
|
||||
if(sphere && specialland == laHalloween) {
|
||||
if(specialcode) return;
|
||||
|
@ -814,6 +833,7 @@ EX void achievement_final(bool really_final) {
|
|||
if(ineligible_starting_land) return;
|
||||
if(geometry) return;
|
||||
if(NONSTDVAR) return;
|
||||
if(use_custom_land_list) return;
|
||||
|
||||
if(numplayers() > 1 && !multi::friendly_fire) return;
|
||||
if(numplayers() > 1 && multi::pvp_mode) return;
|
||||
|
@ -896,7 +916,7 @@ EX void check_total_victory() {
|
|||
EX void achievement_victory(bool hyper) {
|
||||
DEBBI(DF_STEAM, ("achievement_victory"))
|
||||
if(offlineMode) return;
|
||||
#ifdef HAVE_ACHIEVEMENTS
|
||||
#if CAP_ACHIEVE
|
||||
if(cheater) return;
|
||||
if(casual) return;
|
||||
if(bow::weapon) return;
|
||||
|
@ -909,6 +929,7 @@ EX void achievement_victory(bool hyper) {
|
|||
if(tactic::on) return;
|
||||
if(!ls::nice_walls()) return;
|
||||
if(ineligible_starting_land) return;
|
||||
if(use_custom_land_list) return;
|
||||
LATE( achievement_victory(hyper); )
|
||||
DEBB(DF_STEAM, ("after checks"))
|
||||
|
||||
|
@ -1029,13 +1050,9 @@ EX string get_rich_presence_text() {
|
|||
return res;
|
||||
}
|
||||
|
||||
#ifndef HAVE_ACHIEVEMENTS
|
||||
void achievement_pump() {}
|
||||
#endif
|
||||
|
||||
/** display the last achievement gained. */
|
||||
EX void achievement_display() {
|
||||
#ifdef HAVE_ACHIEVEMENTS
|
||||
#if CAP_ACHIEVE
|
||||
if(achievementTimer) {
|
||||
int col = (ticks - achievementTimer);
|
||||
if(col > 5000) { achievementTimer = 0; return; }
|
||||
|
@ -1065,9 +1082,4 @@ EX int score_default(int i) {
|
|||
else return 0;
|
||||
}
|
||||
|
||||
#ifndef HAVE_ACHIEVEMENTS
|
||||
EX int get_sync_status() { return 0; }
|
||||
EX void set_priority_board(int) { }
|
||||
#endif
|
||||
|
||||
}
|
||||
|
|
|
@ -220,8 +220,7 @@ void ensure_geometry(eGeometryClass c) {
|
|||
|
||||
if(specialland != laCanvas) {
|
||||
canvas_default_wall = waInvisibleFloor;
|
||||
patterns::whichCanvas = 'g';
|
||||
patterns::canvasback = 0xFFFFFF;
|
||||
ccolor::set_plain(0xFFFFFF);
|
||||
enable_canvas();
|
||||
}
|
||||
start_game();
|
||||
|
@ -1283,7 +1282,7 @@ void connection_debugger() {
|
|||
|
||||
curvepoint(sh[0]);
|
||||
|
||||
color_t col = colortables['A'][id];
|
||||
color_t col = ccolor::shape.ctab[id];
|
||||
col = darkena(col, 0, 0xFF);
|
||||
|
||||
if(&p == &last) {
|
||||
|
|
|
@ -1340,11 +1340,12 @@ EX void enable(archimedean_tiling& arct) {
|
|||
start_game();
|
||||
}
|
||||
|
||||
function<void()> setcanvas(char c) {
|
||||
return [c] () {
|
||||
function<void()> setcanvas(ccolor::data& c) {
|
||||
auto pc = &c;
|
||||
return [pc] () {
|
||||
stop_game();
|
||||
enable_canvas();
|
||||
patterns::whichCanvas = c;
|
||||
ccolor::which = pc;
|
||||
start_game();
|
||||
};
|
||||
}
|
||||
|
@ -1467,9 +1468,9 @@ EX void show() {
|
|||
dialog::addSelItem(XLAT("edge length"), current.get_class() == gcEuclid ? (fts(current.edgelength) + XLAT(" (arbitrary)")) : fts(current.edgelength), 0);
|
||||
|
||||
dialog::addItem(XLAT("color by symmetries"), 't');
|
||||
dialog::add_action(setcanvas('A'));
|
||||
dialog::add_action(setcanvas(ccolor::shape));
|
||||
dialog::addItem(XLAT("color by symmetries (reversed tiles marked)"), 'r');
|
||||
dialog::add_action(setcanvas('R'));
|
||||
dialog::add_action(setcanvas(ccolor::shape_mirror));
|
||||
}
|
||||
else {
|
||||
dialog::addBreak(100);
|
||||
|
@ -1479,20 +1480,20 @@ EX void show() {
|
|||
|
||||
if(true) {
|
||||
dialog::addItem(XLAT("color by sides"), 'u');
|
||||
dialog::add_action(setcanvas('B'));
|
||||
dialog::add_action(setcanvas(ccolor::sides));
|
||||
}
|
||||
|
||||
if(geosupport_threecolor() == 2) {
|
||||
dialog::addItem(XLAT("three colors"), 'w');
|
||||
dialog::add_action(setcanvas('T'));
|
||||
dialog::add_action(setcanvas(ccolor::threecolor));
|
||||
}
|
||||
else if(geosupport_football() == 2) {
|
||||
dialog::addItem(XLAT("football"), 'w');
|
||||
dialog::add_action(setcanvas('F'));
|
||||
dialog::add_action(setcanvas(ccolor::football));
|
||||
}
|
||||
else if(geosupport_chessboard()) {
|
||||
dialog::addItem(XLAT("chessboard"), 'w');
|
||||
dialog::add_action(setcanvas('c'));
|
||||
dialog::add_action(setcanvas(ccolor::chessboard));
|
||||
}
|
||||
else dialog::addBreak(100);
|
||||
|
||||
|
|
30
attack.cpp
30
attack.cpp
|
@ -137,8 +137,8 @@ EX bool canAttack(cell *c1, eMonster m1, cell *c2, eMonster m2, flagtype flags)
|
|||
else return false;
|
||||
}
|
||||
|
||||
if(flags & AF_APPROACH) {
|
||||
if(m2 == moLancer) ;
|
||||
if(flags & (AF_APPROACH | AF_HORNS)) {
|
||||
if(m2 == moLancer && (flags & AF_APPROACH)) ;
|
||||
else if((flags & AF_HORNS) && checkOrb(m1, itOrbHorns)) { flags |= AF_IGNORE_UNARMED; }
|
||||
else return false;
|
||||
}
|
||||
|
@ -151,7 +151,7 @@ EX bool canAttack(cell *c1, eMonster m1, cell *c2, eMonster m2, flagtype flags)
|
|||
if(!(flags & (AF_GUN | AF_SWORD | AF_SWORD_INTO | AF_MAGIC | AF_PLAGUE)))
|
||||
if(c1 != c2 && !logical_adjacent(c1, m1, c2)) return false;
|
||||
|
||||
if(!(flags & (AF_LANCE | AF_STAB | AF_BACK | AF_APPROACH | AF_GUN | AF_MAGIC | AF_PLAGUE | AF_SIDE)))
|
||||
if(!(flags & (AF_LANCE | AF_STAB | AF_BACK | AF_APPROACH | AF_GUN | AF_MAGIC | AF_PLAGUE | AF_SIDE | AF_BOW)))
|
||||
if(c1 && c2 && againstRose(c1, c2) && !ignoresSmell(m1))
|
||||
return false;
|
||||
|
||||
|
@ -757,6 +757,11 @@ EX void killMonster(cell *c, eMonster who, flagtype deathflags IS(0)) {
|
|||
// a reward for killing him before he shoots!
|
||||
c->item = itOrbDragon;
|
||||
}
|
||||
if(m == moAsteroid && !shmup::on && c->item == itNone && c->wall != waChasm && c->land == laAsteroids) {
|
||||
c->item = itAsteroid;
|
||||
changes.value_add(splitrocks, 2);
|
||||
}
|
||||
|
||||
if(m == moOutlaw && (c->item == itNone || c->item == itRevolver) && c->wall != waChasm)
|
||||
c->item = itBounty;
|
||||
// note: an Orb appears underwater!
|
||||
|
@ -939,6 +944,14 @@ EX void fightmessage(eMonster victim, eMonster attacker, bool stun, flagtype fla
|
|||
else
|
||||
addMessage(XLAT("You pierce %the1.", victim)); // normal
|
||||
}
|
||||
else if(items[itOrbSlaying]) {
|
||||
playSound(NULL, "hit-crush"+pick123());
|
||||
addMessage(XLAT("You crush %the1!", victim)); // normal
|
||||
}
|
||||
else if(stun && items[itCurseWeakness]) {
|
||||
playSound(NULL, "click");
|
||||
addMessage(XLAT("You punch %the1.", victim)); // normal
|
||||
}
|
||||
else if(!peace::on) {
|
||||
playSound(NULL, "hit-sword"+pick123());
|
||||
addMessage(XLAT("You kill %the1.", victim)); // normal
|
||||
|
@ -1111,11 +1124,11 @@ EX bool should_switchplace(cell *c1, cell *c2) {
|
|||
EX bool switchplace_prevent(cell *c1, cell *c2, struct pcmove& m) {
|
||||
if(!should_switchplace(c1, c2)) return false;
|
||||
if(peace::on && (isMultitile(c2->monst) || saved_tortoise_on(c2) || isDie(c2->monst))) {
|
||||
if(m.vmsg(miRESTRICTED)) addMessage(XLAT("Cannot switch places with %the1!", c2->monst));
|
||||
if(m.vmsg(miRESTRICTED, siMONSTER, c2, c2->monst)) addMessage(XLAT("Cannot switch places with %the1!", c2->monst));
|
||||
return true;
|
||||
}
|
||||
if(c1->monst && c1->monst != moFriendlyIvy) {
|
||||
if(m.vmsg(miRESTRICTED)) addMessage(XLAT("There is no room for %the1!", c2->monst));
|
||||
if(m.vmsg(miRESTRICTED, siMONSTER, c1, c1->monst)) addMessage(XLAT("There is no room for %the1!", c2->monst));
|
||||
return true;
|
||||
}
|
||||
if(passable(c1, c2, P_ISFRIEND | (c2->monst == moTameBomberbird ? P_FLYING : 0))) return false;
|
||||
|
@ -1227,11 +1240,13 @@ EX void killThePlayer(eMonster m, int id, flagtype flags) {
|
|||
}
|
||||
else if(hardcore) {
|
||||
addMessage(XLAT("You are killed by %the1!", m));
|
||||
yasc_message = XLAT("killed by %the1", m);
|
||||
killHardcorePlayer(id, flags);
|
||||
}
|
||||
else if(m == moLightningBolt && lastmovetype == lmAttack && isAlchAny(playerpos(id))) {
|
||||
addMessage(XLAT("You are killed by %the1!", m));
|
||||
addMessage(XLAT("Don't play with slime and electricity next time, okay?"));
|
||||
yasc_message = XLAT("killed by %the1", m);
|
||||
kills[moPlayer]++;
|
||||
items[itOrbSafety] = 0;
|
||||
}
|
||||
|
@ -1346,9 +1361,10 @@ EX void stabbingAttack(movei mi, eMonster who, int bonuskill IS(0)) {
|
|||
forCellIdEx(c, t, mt) {
|
||||
if(!logical_adjacent(mt, who, c)) continue;
|
||||
eMonster mm = c->monst;
|
||||
int flag = AF_APPROACH;
|
||||
int flag = 0;
|
||||
if(!isUnarmed(who) && !out) flag |= AF_APPROACH;
|
||||
if(proper(mt, backdir) && anglestraight(mt, backdir, t)) flag |= AF_HORNS;
|
||||
if((isUnarmed(who) || out) && !(flag & AF_HORNS)) continue;
|
||||
if(!flag) continue;
|
||||
if(canAttack(mt,who,c,c->monst, flag)) {
|
||||
changes.ccell(c);
|
||||
if(attackMonster(c, flag | AF_MSG, who)) numlance++;
|
||||
|
|
136
barriers.cpp
136
barriers.cpp
|
@ -559,7 +559,9 @@ EX bool isbar4(cell *c) {
|
|||
}
|
||||
|
||||
EX bool barrier_cross(eLand l, eLand r) {
|
||||
if(land_structure == lsVineWalls) return false;
|
||||
if(l == laCrossroads3 || r == laCrossroads3) return hrand(100) < 66;
|
||||
if(land_structure == lsCrossWalls && !among(laCrossroads2, l, r)) return hrand(100) < 90;
|
||||
if(isElemental(l) && isElemental(r)) return hrand(100) < 75;
|
||||
return false;
|
||||
}
|
||||
|
@ -615,6 +617,12 @@ EX void extendBarrier(cell *c) {
|
|||
if(buildBarrier6(cw, 2)) return;
|
||||
}
|
||||
|
||||
if(land_structure == lsCursedWalls && c->barleft != laMirror && c->barright != laMirror && hrand(100) < 80 && !among(laCrossroads2, c->barleft, c->barright)) {
|
||||
cellwalker cw(c, c->bardir);
|
||||
cw = cw + wstep + 3 + wstep - 1;
|
||||
if(buildBarrier6(cw, c->barright, c->barleft)) return;
|
||||
}
|
||||
|
||||
if(barrier_cross(c->barleft, c->barright) || (firstmirror && hrand(100) < 60)) {
|
||||
|
||||
cellwalker cw(c, c->bardir);
|
||||
|
@ -680,6 +688,7 @@ EX void buildBarrier(cell *c, int d, eLand l IS(laNone)) {
|
|||
buildBarrierForce(c, d, l);
|
||||
}
|
||||
|
||||
/** mirror variant of 6-fold walls */
|
||||
EX bool buildBarrier6(cellwalker cw, int type) {
|
||||
limitgen("build6 %p/%d (%d)\n", hr::voidp(cw.at), cw.spin, type);
|
||||
|
||||
|
@ -724,21 +733,28 @@ EX bool buildBarrier6(cellwalker cw, int type) {
|
|||
if(!(PURE?checkBarriersFront:checkBarriersBack)(b[0], 6, true)) return false;
|
||||
if(!(PURE?checkBarriersFront:checkBarriersBack)(b[3], 6, true)) return false;
|
||||
}
|
||||
|
||||
|
||||
eLand m0 = laMirror;
|
||||
eLand m1 = laMirrored;
|
||||
eLand m2 = laMirrored2;
|
||||
eLand mw1 = laMirrorWall;
|
||||
eLand mw2 = laMirrorWall2;
|
||||
eWall w = waMirrorWall;
|
||||
|
||||
for(int d=0; d<4; d++) {
|
||||
b[d].at->bardir = b[d].spin;
|
||||
|
||||
if(PURE) {
|
||||
b[0].at->barleft = laMirrored, b[0].at->barright = laMirrored2;
|
||||
b[1].at->barleft = laMirror, b[1].at->barright = laMirrored;
|
||||
b[2].at->barleft = laMirrored2, b[2].at->barright = laMirrored;
|
||||
b[3].at->barleft = laMirrored, b[3].at->barright = laMirror;
|
||||
b[0].at->barleft = m1, b[0].at->barright = m2;
|
||||
b[1].at->barleft = m0, b[1].at->barright = m1;
|
||||
b[2].at->barleft = m2, b[2].at->barright = m1;
|
||||
b[3].at->barleft = m1, b[3].at->barright = m0;
|
||||
}
|
||||
else {
|
||||
b[0].at->barleft = laMirror, b[0].at->barright = laMirrored;
|
||||
b[1].at->barleft = laMirrored, b[1].at->barright = laMirror;
|
||||
b[2].at->barleft = laMirrored, b[2].at->barright = laMirrored2;
|
||||
b[3].at->barleft = laMirrored2, b[3].at->barright = laMirrored;
|
||||
b[0].at->barleft = m0, b[0].at->barright = m1;
|
||||
b[1].at->barleft = m1, b[1].at->barright = m0;
|
||||
b[2].at->barleft = m1, b[2].at->barright = m2;
|
||||
b[3].at->barleft = m2, b[3].at->barright = m1;
|
||||
}
|
||||
|
||||
(PURE?extendBarrierFront:extendBarrierBack)(b[d].at);
|
||||
|
@ -752,45 +768,87 @@ EX bool buildBarrier6(cellwalker cw, int type) {
|
|||
}
|
||||
|
||||
if(BITRUNCATED) {
|
||||
setland((cw+1).cpeek(), laMirrorWall);
|
||||
setland((cw+2).cpeek(), laMirrored);
|
||||
setland((cw+3).cpeek(), laMirrorWall2);
|
||||
setland((cw+4).cpeek(), laMirrorWall2);
|
||||
setland((cw+5).cpeek(), laMirrored);
|
||||
setland((cw+0).cpeek(), laMirrorWall);
|
||||
setland((b[0]+2).cpeek(), laMirrored);
|
||||
setland((b[3]+6).cpeek(), laMirrored2);
|
||||
setland((b[3]+5).cpeek(), laMirrored2);
|
||||
setland((b[1]-1).cpeek(), laMirrored);
|
||||
setland((b[2]-2).cpeek(), laMirrored);
|
||||
setland((b[1]-2).cpeek(), laMirrored);
|
||||
setland((b[0]-2).cpeek(), laMirror);
|
||||
cw.at->land = laMirrorWall;
|
||||
cw.at->wall = waMirrorWall;
|
||||
setland((cw+1).cpeek(), mw1);
|
||||
setland((cw+2).cpeek(), m1);
|
||||
setland((cw+3).cpeek(), mw2);
|
||||
setland((cw+4).cpeek(), mw2);
|
||||
setland((cw+5).cpeek(), m1);
|
||||
setland((cw+0).cpeek(), mw1);
|
||||
setland((b[0]+2).cpeek(), m1);
|
||||
setland((b[3]+6).cpeek(), m2);
|
||||
setland((b[3]+5).cpeek(), m2);
|
||||
setland((b[1]-1).cpeek(), m1);
|
||||
setland((b[2]-2).cpeek(), m1);
|
||||
setland((b[1]-2).cpeek(), m1);
|
||||
setland((b[0]-2).cpeek(), m0);
|
||||
cw.at->land = mw1;
|
||||
cw.at->wall = w;
|
||||
cw.at->landparam = 1;
|
||||
}
|
||||
else {
|
||||
setland(cw.at, laMirrorWall2);
|
||||
setland((cw+0).cpeek(), laMirrorWall2);
|
||||
setland((cw+1).cpeek(), laMirrored);
|
||||
setland((cw+2).cpeek(), laMirrored);
|
||||
setland((cw+3).cpeek(), laMirrorWall);
|
||||
setland((cw+4).cpeek(), laMirrored);
|
||||
setland((cw+5).cpeek(), laMirrorWall2);
|
||||
setland((cw+6).cpeek(), laMirrored2);
|
||||
setland(cw.at, mw2);
|
||||
setland((cw+0).cpeek(), mw2);
|
||||
setland((cw+1).cpeek(), m1);
|
||||
setland((cw+2).cpeek(), m1);
|
||||
setland((cw+3).cpeek(), mw1);
|
||||
setland((cw+4).cpeek(), m1);
|
||||
setland((cw+5).cpeek(), mw2);
|
||||
setland((cw+6).cpeek(), m2);
|
||||
|
||||
setland((b[1]).cpeek(), laMirrorWall);
|
||||
setland((b[1]+1).cpeek(), laMirror);
|
||||
setland((b[1]+2).cpeek(), laMirrorWall);
|
||||
setland((b[1]+6).cpeek(), laMirrored);
|
||||
setland((b[1]).cpeek(), mw1);
|
||||
setland((b[1]+1).cpeek(), m0);
|
||||
setland((b[1]+2).cpeek(), mw1);
|
||||
setland((b[1]+6).cpeek(), m1);
|
||||
|
||||
setland((b[0] + wstep - 2).cpeek(), laMirrored);
|
||||
setland((b[3] + wstep - 2).cpeek(), laMirrored);
|
||||
setland((b[0] + wstep - 2).cpeek(), m1);
|
||||
setland((b[3] + wstep - 2).cpeek(), m1);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
EX int curse_percentage = 10;
|
||||
|
||||
/** cursed variant of 6-fold walls */
|
||||
EX bool buildBarrier6(cellwalker cw, eLand m0, eLand m1) {
|
||||
cellwalker b[6];
|
||||
if(buggyGeneration) return true;
|
||||
|
||||
for(int i=0; i<6; i+=2)
|
||||
b[i] = cw + i + wstep;
|
||||
for(int i=1; i<6; i+=2)
|
||||
b[i] = cw + i + wstep + 3 + wstep;
|
||||
|
||||
for(int i=0; i<6; i++) if(i != 1) {
|
||||
if(!(PURE?checkBarriersFront:checkBarriersBack)(b[i], 6, true)) return false;
|
||||
}
|
||||
|
||||
for(int d=0; d<6; d++) {
|
||||
b[d].at->bardir = b[d].spin;
|
||||
b[d].at->barleft = (d&1) ? m1 : m0;
|
||||
b[d].at->barright = (d&1) ? m0 : m1;
|
||||
(PURE?extendBarrierFront:extendBarrierBack)(b[d].at);
|
||||
}
|
||||
|
||||
cw.at->land = laBarrier;
|
||||
cw.at->wall = waBarrier;
|
||||
forCellCM(c, cw.at) { c->land = laBarrier; c->wall = waBarrier; }
|
||||
for(int d=0; d<6; d+=2) {
|
||||
setland((b[d]-2).cpeek(), m0);
|
||||
setland((b[d]+2).cpeek(), m1);
|
||||
setland((b[d+1]-2).cpeek(), m1);
|
||||
setland((b[d+1]+2).cpeek(), m0);
|
||||
}
|
||||
if(hrand(100) < curse_percentage) {
|
||||
setland(cw.at, laCursed);
|
||||
cw.at->wall = waRubble;
|
||||
cw.at->monst = moHexer;
|
||||
cw.at->item = random_curse();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
EX bool buildBarrier4(cell *c, int d, int mode, eLand ll, eLand lr) {
|
||||
limitgen("build4 %p\n", hr::voidp(c));
|
||||
if(buggyGeneration) return true;
|
||||
|
|
46
bigstuff.cpp
46
bigstuff.cpp
|
@ -703,6 +703,9 @@ EX int coastval(cell *c, eLand base) {
|
|||
if(!c->landparam) return UNKNOWN;
|
||||
return c->landparam & 255;
|
||||
}
|
||||
else if(base == laWestWall) {
|
||||
if(c->land != base) return 0;
|
||||
}
|
||||
else {
|
||||
if(c->land == laOceanWall || c->land == laCaribbean || c->land == laWhirlpool ||
|
||||
c->land == laLivefjord || c->land == laWarpSea || c->land == laKraken || c->land == laDocks || c->land == laBrownian)
|
||||
|
@ -1005,7 +1008,7 @@ EX void buildEquidistant(cell *c) {
|
|||
if(c->landparam > 30 && b == laOcean && !generatingEquidistant && !mhybrid && hrand(10) < 5 && chance)
|
||||
buildAnotherEquidistant(c);
|
||||
|
||||
if(c->landparam > HAUNTED_RADIUS+5 && b == laGraveyard && !generatingEquidistant && !mhybrid && hrand(100) < (PURE?25:5) && items[itBone] >= U10 && chance)
|
||||
if(c->landparam > HAUNTED_RADIUS+5 && b == laGraveyard && !generatingEquidistant && !mhybrid && hrand(100) < (PURE?25:5) && landUnlockedIngame(laHaunted) && chance)
|
||||
buildAnotherEquidistant(c);
|
||||
}
|
||||
|
||||
|
@ -1132,6 +1135,7 @@ EX void setLandSphere(cell *c) {
|
|||
vector<eLand> euland;
|
||||
map<int, eLand> euland3;
|
||||
map<int, eLand> euland3_hash;
|
||||
EX map<array<int, 3>, eLand> landscape_lands;
|
||||
|
||||
EX eLand& get_euland(int c) {
|
||||
euland.resize(max_vec);
|
||||
|
@ -1144,6 +1148,8 @@ EX void clear_euland(eLand first) {
|
|||
if(!nonisotropic) euland[0] = euland[1] = euland[max_vec-1] = first;
|
||||
euland3.clear();
|
||||
euland3[0] = first;
|
||||
landscape_lands.clear();
|
||||
landscape_lands[make_array(0,0,0)] = first;
|
||||
}
|
||||
|
||||
bool valid_wall_at(int c) {
|
||||
|
@ -1323,7 +1329,7 @@ EX void setLandEuclid(cell *c) {
|
|||
return;
|
||||
}
|
||||
#endif
|
||||
setland(c, specialland);
|
||||
if(!c->land) setland(c, specialland);
|
||||
if(ls::any_nowall()) {
|
||||
auto co = euc2_coordinates(c);
|
||||
int y = co.second;
|
||||
|
@ -1768,6 +1774,21 @@ EX void build_walls(cell *c, cell *from) {
|
|||
|
||||
else if(good_for_wall(c) && isWarpedType(c->land) && hrand(10000) < 3000 && c->land &&
|
||||
buildBarrierNowall(c, eLand(c->land ^ laWarpSea ^ laWarpCoast))) { }
|
||||
|
||||
else if(land_structure == lsVineWalls) {
|
||||
int ev = emeraldval(c);
|
||||
if((ev | 11) == 43 && c->bardir == NODIR) {
|
||||
for(int i=0; i<c->type; i++) if(emeraldval(c->cmove(i)) == ev-4) {
|
||||
bool oldleft = true;
|
||||
for(int j=1; j<=3; j++)
|
||||
if(c->modmove(i+j) && c->modmove(i+j)->mpdist < c->mpdist)
|
||||
oldleft = false;
|
||||
buildBarrierStrong(c, i, oldleft, getNewLand(c->land));
|
||||
extendBarrier(c);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
else if(ls::single()) return;
|
||||
|
||||
|
@ -1789,11 +1810,11 @@ EX void build_walls(cell *c, cell *from) {
|
|||
return;
|
||||
}
|
||||
|
||||
else if(good_for_wall(c) && c->land == laCrossroads4 && hrand(10000) < 7000 && c->land && !c->master->alt && !tactic::on && !racing::on &&
|
||||
else if(good_for_wall(c) && ls::any_wall() && c->land == laCrossroads4 && hrand(10000) < 7000 && c->land && !c->master->alt && !tactic::on && !racing::on &&
|
||||
buildBarrierNowall(c, getNewLand(laCrossroads4))) ;
|
||||
|
||||
else if(good_for_wall(c) && hrand(I10000) < 20 && !generatingEquidistant && !yendor::on && !tactic::on && !racing::on && !isCrossroads(c->land) &&
|
||||
gold() >= R200 && !weirdhyperbolic && !c->master->alt && c->bardir != NOBARRIERS &&
|
||||
else if(good_for_wall(c) && ls::any_wall() && hrand(I10000) < 20 && !generatingEquidistant && !yendor::on && !tactic::on && !racing::on && !isCrossroads(c->land) &&
|
||||
landUnlockedIngame(laCrossroads4) && !weirdhyperbolic && !c->master->alt && c->bardir != NOBARRIERS &&
|
||||
!inmirror(c) && !isSealand(c->land) && !isHaunted(c->land) && !isGravityLand(c->land) &&
|
||||
(c->land != laRlyeh || rlyehComplete()) &&
|
||||
c->land != laTortoise && c->land != laPrairie && c->land &&
|
||||
|
@ -1873,13 +1894,13 @@ EX void build_horocycles(cell *c, cell *from) {
|
|||
items[itEmerald] >= U5)))
|
||||
start_camelot(c);
|
||||
|
||||
if(c->land == laRlyeh && can_start_horo(c) && (quickfind(laTemple) || peace::on || (hrand(I2000) < 100 && items[itStatue] >= U5)))
|
||||
if(c->land == laRlyeh && can_start_horo(c) && (quickfind(laTemple) || (hrand(I2000) < 100 && landUnlockedIngame(laTemple))))
|
||||
create_altmap(c, horo_gen_distance(), hsA);
|
||||
|
||||
if(c->land == laJungle && can_start_horo(c) && (quickfind(laMountain) || (hrand(I2000) < 100 && landUnlocked(laMountain))))
|
||||
if(c->land == laJungle && can_start_horo(c) && (quickfind(laMountain) || (hrand(I2000) < 100 && landUnlockedIngame(laMountain))))
|
||||
create_altmap(c, horo_gen_distance(), hsA);
|
||||
|
||||
if(c->land == laOvergrown && can_start_horo(c) && (quickfind(laClearing) || (hrand(I2000) < 25 && items[itMutant] >= U5 && isLandIngame(laClearing)))) {
|
||||
if(c->land == laOvergrown && can_start_horo(c) && (quickfind(laClearing) || (hrand(I2000) < 25 && landUnlockedIngame(laClearing)))) {
|
||||
heptagon *h = create_altmap(c, horo_gen_distance(), hsA);
|
||||
if(h) clearing::bpdata[h].root = NULL;
|
||||
}
|
||||
|
@ -1891,11 +1912,12 @@ EX void build_horocycles(cell *c, cell *from) {
|
|||
|
||||
if(c->land == laOcean && deepOcean && !generatingEquidistant && !peace::on && can_start_horo(c) &&
|
||||
(quickfind(laWhirlpool) || (
|
||||
hrand(2000) < (PURE ? 500 : 1000))))
|
||||
hrand(2000) < (PURE ? 500 : 1000) && landUnlockedIngame(laWhirlpool))))
|
||||
create_altmap(c, horo_gen_distance(), hsA);
|
||||
|
||||
#if CAP_COMPLEX2
|
||||
if(c->land == laOcean && deepOcean && !generatingEquidistant && hrand(10000) < 20 && no_barriers_in_radius(c, 2) && hyperbolic && !quotient && !tactic::on && !safety && !ls::hv_structure())
|
||||
if(c->land == laOcean && deepOcean && !generatingEquidistant && hrand(10000) < 20 && no_barriers_in_radius(c, 2) && hyperbolic && !quotient && !tactic::on && !safety && !ls::hv_structure()
|
||||
&& landUnlockedIngame(laBrownian))
|
||||
brownian::init_further(c);
|
||||
#endif
|
||||
|
||||
|
@ -1916,7 +1938,7 @@ EX void build_horocycles(cell *c, cell *from) {
|
|||
if(c->land == laPalace && can_start_horo(c) && !princess::generating && !shmup::on && multi::players == 1 && !weirdhyperbolic &&
|
||||
(princess::forceMouse ? canReachPlayer(from, moMouse) :
|
||||
(hrand(2000) < (peace::on ? 100 : 20))) &&
|
||||
(princess::challenge || kills[moVizier] || peace::on)) {
|
||||
landUnlockedIngame(laPrincessQuest)) {
|
||||
create_altmap(c, PRADIUS0, hsOrigin, waPalace);
|
||||
celllister cl(c, 5, 1000000, NULL);
|
||||
for(cell *c: cl.lst) if(c->master->alt) currentmap->extend_altmap(c->master);
|
||||
|
@ -2315,7 +2337,7 @@ EX void pregen() {
|
|||
currentlands.clear();
|
||||
if(ls::any_chaos() && !ls::std_chaos())
|
||||
for(eLand l: land_over)
|
||||
if(landUnlocked(l) && isLandIngame(l))
|
||||
if(landUnlockedIngame(l))
|
||||
currentlands.push_back(l);
|
||||
}
|
||||
|
||||
|
|
|
@ -136,7 +136,7 @@ EX namespace bt {
|
|||
h->emeraldval = gmod((parent->emeraldval - d1) * 7508, 15015);
|
||||
break;
|
||||
case gTernary:
|
||||
if(d < 2)
|
||||
if(d <= 2)
|
||||
h->emeraldval = gmod(parent->emeraldval * 3 + d, 10010);
|
||||
else
|
||||
h->emeraldval = gmod((parent->emeraldval - d1) * 3337, 10010);
|
||||
|
@ -854,14 +854,35 @@ auto bt_config = arg::add2("-btwidth", [] {arg::shift_arg_formula(vid.binary_wid
|
|||
#endif
|
||||
|
||||
EX bool pseudohept(cell *c) {
|
||||
if(WDIM == 2)
|
||||
return c->type & c->master->distance & 1;
|
||||
else if(geometry == gHoroRec)
|
||||
return c->c.spin(S7-1) == 0 && (c->master->distance & 1) && c->cmove(S7-1)->c.spin(S7-1) == 0;
|
||||
else if(geometry == gHoroTris)
|
||||
return c->c.spin(S7-1) == 0 && (c->master->distance & 1);
|
||||
else
|
||||
return (c->master->zebraval == 1) && (c->master->distance & 1);
|
||||
switch(geometry) {
|
||||
case gBinary4:
|
||||
c->cmove(3);
|
||||
return (c->master->distance & 1) && (c->c.spin(3) == 0);
|
||||
|
||||
case gBinaryTiling:
|
||||
return c->master->distance & c->type & 1;
|
||||
|
||||
case gTernary: {
|
||||
return c->master->emeraldval & 1;
|
||||
/* auto m = dynamic_cast<hrmap_binary*> (current_map());
|
||||
auto o = m->origin;
|
||||
int flips = 0;
|
||||
while(m != o) {
|
||||
if(m->master->distance >= o->master->distance) { if(m->c.spin(4) == 1) flips++; m = m->cmove(4); }
|
||||
}
|
||||
heptagon *origin;
|
||||
c->cmove(4); return (c->c.spin(4) == 1); */
|
||||
}
|
||||
|
||||
case gHoroRec:
|
||||
return c->c.spin(S7-1) == 0 && (c->master->distance & 1) && c->cmove(S7-1)->c.spin(S7-1) == 0;
|
||||
|
||||
case gHoroTris:
|
||||
return c->c.spin(S7-1) == 0 && (c->master->distance & 1);
|
||||
|
||||
default:
|
||||
return (c->master->zebraval == 1) && (c->master->distance & 1);
|
||||
}
|
||||
}
|
||||
|
||||
EX pair<gp::loc, gp::loc> gpvalue(heptagon *h) {
|
||||
|
|
7
cell.cpp
7
cell.cpp
|
@ -1469,14 +1469,15 @@ EX int celldistance(cell *c1, cell *c2) {
|
|||
if(hyperbolic && WDIM == 3) return reg3::celldistance(c1, c2);
|
||||
#endif
|
||||
|
||||
if(INVERSE) {
|
||||
/* if(INVERSE) {
|
||||
c1 = gp::get_mapped(c1);
|
||||
c2 = gp::get_mapped(c2);
|
||||
return UIU(celldistance(c1, c2)) / 2;
|
||||
/* TODO */
|
||||
}
|
||||
// that does not seem to work
|
||||
} */
|
||||
|
||||
if(euclid) return clueless_celldistance(c1, c2);
|
||||
if(INVERSE) return clueless_celldistance(c1, c2);
|
||||
|
||||
return hyperbolic_celldistance(c1, c2);
|
||||
}
|
||||
|
|
135
celldrawer.cpp
135
celldrawer.cpp
|
@ -94,6 +94,14 @@ void eclectic_red(color_t& col) {
|
|||
|
||||
constexpr ld spinspeed = .75 / M_PI;
|
||||
|
||||
EX color_t apply_mine_knowledge(color_t wcol, cell* c) {
|
||||
if(mine::marked_safe(c))
|
||||
return gradient(wcol, 0x40FF40, 0, 0.2, 1);
|
||||
if(mine::marked_mine(c))
|
||||
return gradient(wcol, 0xFF4040, -1, vid.ispeed ? sintick(100) : 1, 1);
|
||||
return wcol;
|
||||
}
|
||||
|
||||
void celldrawer::setcolors() {
|
||||
|
||||
wcol = fcol = winf[c->wall].color;
|
||||
|
@ -541,10 +549,7 @@ void celldrawer::setcolors() {
|
|||
|
||||
case waMineUnknown: case waMineMine:
|
||||
#if CAP_COMPLEX2
|
||||
if(mine::marked_safe(c))
|
||||
fcol = wcol = gradient(wcol, 0x40FF40, 0, 0.2, 1);
|
||||
else if(mine::marked_mine(c))
|
||||
fcol = wcol = gradient(wcol, 0xFF4040, -1, vid.ispeed ? sintick(100) : 1, 1);
|
||||
if(!mine_markers) fcol = wcol = apply_mine_knowledge(wcol, c);
|
||||
goto fallthrough;
|
||||
#endif
|
||||
|
||||
|
@ -847,13 +852,6 @@ void celldrawer::draw_grid() {
|
|||
|
||||
int prec = grid_prec();
|
||||
|
||||
if(vid.grid && c->bardir != NODIR && c->bardir != NOBARRIERS && c->land != laHauntedWall &&
|
||||
c->barleft != NOWALLSEP_USED && GDIM == 2) {
|
||||
color_t col = darkena(0x505050, 0, 0xFF);
|
||||
gridline(V, C0, tC0(cgi.heptmove[c->bardir]), col, prec+1);
|
||||
gridline(V, C0, tC0(cgi.hexmove[c->bardir]), col, prec+1);
|
||||
}
|
||||
|
||||
if(inmirrorcount) return;
|
||||
|
||||
if(vid.grid || (c->land == laAsteroids && !(WDIM == 2 && GDIM == 3))) ; else return;
|
||||
|
@ -1386,6 +1384,39 @@ bool celldrawer::set_randompattern_floor() {
|
|||
}
|
||||
|
||||
EX bool numerical_minefield;
|
||||
EX int mine_zero_display = 1;
|
||||
EX bool mine_hollow;
|
||||
EX bool mine_markers;
|
||||
|
||||
EX void draw_mine_numbers(int mines, const shiftmatrix& V, int ct6) {
|
||||
auto hollow = [&] (hpcshape& sh, color_t col) {
|
||||
if(mine_hollow) {
|
||||
dynamicval<color_t> dc(poly_outline, col);
|
||||
queuepoly(V, sh, 0);
|
||||
}
|
||||
else
|
||||
queuepoly(V, sh, col);
|
||||
};
|
||||
if(mines == 0 && mine_zero_display < (WDIM == 3 ? 1 : 2)) return;
|
||||
if(numerical_minefield) {
|
||||
string label = its(mines);
|
||||
queuestr(V, (mines >= 10 ? .5 : 1) * mapfontscale / 100, label, darkened(minecolors[mines]), 8);
|
||||
}
|
||||
else {
|
||||
if(mines >= isize(minecolors)) hollow(cgi.shBigMineMark[ct6], darkena(minecolors[mines/isize(minecolors)], 0, 0xFF));
|
||||
hollow(cgi.shMineMark[ct6], darkena(minecolors[mines], 0, 0xFF));
|
||||
}
|
||||
}
|
||||
|
||||
EX void draw_mine_markers(cell *c, const shiftmatrix& V) {
|
||||
if(mine_markers && !mine::marked_safe(c)) {
|
||||
color_t col = 0xFF4040;
|
||||
if(mine::marked_mine(c))
|
||||
col = gradient(winf[waMineMine].color, col, -1, vid.ispeed ? sintick(100) : 1, 1);
|
||||
dynamicval<color_t> dc(poly_outline, (col << 8) | 0xFF);
|
||||
queuepoly(V, cgi.shJoint, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void celldrawer::draw_features() {
|
||||
char xch = winf[c->wall].glyph;
|
||||
|
@ -1631,18 +1662,12 @@ void celldrawer::draw_features() {
|
|||
|
||||
case waMineOpen: {
|
||||
int mines = countMinesAround(c);
|
||||
if(numerical_minefield) {
|
||||
if(mines) {
|
||||
string label = its(mines);
|
||||
queuestr(V, mines >= 10 ? .5 : 1, label, darkened(minecolors[mines]), 8);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(mines >= isize(minecolors))
|
||||
queuepoly(V, cgi.shBigMineMark[ct6], darkena(minecolors[mines/isize(minecolors)], 0, 0xFF));
|
||||
if(mines)
|
||||
queuepoly(V, cgi.shMineMark[ct6], darkena(minecolors[mines], 0, 0xFF));
|
||||
}
|
||||
draw_mine_numbers(mines, V, ct6);
|
||||
break;
|
||||
}
|
||||
|
||||
case waMineUnknown: case waMineMine: {
|
||||
draw_mine_markers(c, V);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1772,6 +1797,9 @@ void celldrawer::draw_features_and_walls_3d() {
|
|||
if(anyshiftclick) return;
|
||||
}
|
||||
|
||||
if(among(c->wall, waMineUnknown, waMineMine))
|
||||
draw_mine_markers(c, face_the_player(V));
|
||||
|
||||
if(isWall3(c, wcol)) {
|
||||
if(!no_wall_rendering) {
|
||||
if(c->wall == waChasm && c->land == laMemory && !in_perspective()) {
|
||||
|
@ -1848,6 +1876,12 @@ void celldrawer::draw_features_and_walls_3d() {
|
|||
queuepoly(V, cgi.shPlainWall3D[ofs + a], darkena(wcol2 - d * get_darkval(c, a), 0, 0xFF));
|
||||
}
|
||||
}
|
||||
if(WDIM == 3 && c->wall == waRose) {
|
||||
color_t col = winf[waRose].color;
|
||||
color_t col2 = (col << 8) | 0xFF;
|
||||
if(rosephase == 7) col2 = 0xFFFFFFFF;
|
||||
addradar(V, winf[waRose].glyph, col, col2);
|
||||
}
|
||||
} }
|
||||
else {
|
||||
if(!no_wall_rendering) for(int a=0; a<c->type; a++) if(c->move(a)) {
|
||||
|
@ -1875,9 +1909,7 @@ void celldrawer::draw_features_and_walls_3d() {
|
|||
}
|
||||
else {
|
||||
int mines = countMinesAround(c);
|
||||
if(mines >= isize(minecolors))
|
||||
queuepoly(face_the_player(V), cgi.shBigMineMark[0], darkena(minecolors[mines/isize(minecolors)], 0, 0xFF));
|
||||
queuepoly(face_the_player(V), cgi.shMineMark[0], darkena(minecolors[mines], 0, 0xFF));
|
||||
draw_mine_numbers(mines, face_the_player(V), 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2079,7 +2111,7 @@ void celldrawer::draw_cellstat() {
|
|||
|
||||
if(c->land == laMirrored || c->land == laMirrorWall2 || c->land == laMirrored2) {
|
||||
string label = its(c->landparam);
|
||||
queuestr(V, 1 * .2, label, 0xFFFFFFFF, 1);
|
||||
queuestr(V, mapfontscale / 500, label, 0xFFFFFFFF, 1);
|
||||
}
|
||||
|
||||
if(debug_tiles && mod_allowed()) {
|
||||
|
@ -2105,22 +2137,22 @@ void celldrawer::draw_cellstat() {
|
|||
#endif
|
||||
else
|
||||
label = its(shvid(c));
|
||||
queuestr(V, .5, label, 0xFFFFFFFF, 1);
|
||||
queuestr(V, mapfontscale / 200, label, 0xFFFFFFFF, 1);
|
||||
for(int i=0; i<c->type; i++) {
|
||||
queuestr(V * rgpushxto0(currentmap->get_corner(c, i, 4)), .2, its(i), 0xFFFFFFFF, 1);
|
||||
queuestr(V * rgpushxto0(mid(currentmap->get_corner(c, i, 4), currentmap->get_corner(c, i+1, 5))), .2, its(i), 0xFFFFFFFF, 1);
|
||||
queuestr(V * rgpushxto0(currentmap->get_corner(c, i, 4)), mapfontscale / 500, its(i), 0xFFFFFFFF, 1);
|
||||
queuestr(V * rgpushxto0(mid(currentmap->get_corner(c, i, 4), currentmap->get_corner(c, i+1, 5))), mapfontscale / 500, its(i), 0xFFFFFFFF, 1);
|
||||
}
|
||||
}
|
||||
|
||||
if(debug_voronoi && ls::voronoi_structure() && mod_allowed()) {
|
||||
if(debug_voronoi && ls::hv_structure() && mod_allowed()) {
|
||||
auto p = get_voronoi_winner(c);
|
||||
queuestr(V, .2, its(p.second), index_pointer_int(p.first) * 0x7F3015, 1);
|
||||
queuestr(V, mapfontscale / 500, its(p.second), index_pointer_int(p.first) * 0x7F3015, 1);
|
||||
}
|
||||
|
||||
if(cmode & sm::TORUSCONFIG) {
|
||||
auto p = euc::coord_display(V, c);
|
||||
if(p.second != "")
|
||||
queuestr(V, p.first ? .2 : .6, p.second, p.first ? 0xFFFFFFD0 : 0xFFFF0040, 1);
|
||||
queuestr(V, (p.first ? .2 : .6) * mapfontscale / 100, p.second, p.first ? 0xFFFFFFD0 : 0xFFFF0040, 1);
|
||||
}
|
||||
|
||||
#if CAP_EDIT
|
||||
|
@ -2135,13 +2167,13 @@ void celldrawer::draw_cellstat() {
|
|||
|
||||
string label = its(si.id & 255);
|
||||
color_t col = forecolor ^ colorhash(si.id >> 8);
|
||||
queuestr(V, .5, label, 0xFF000000 + col);
|
||||
queuestr(V, mapfontscale / 200, label, 0xFF000000 + col);
|
||||
}
|
||||
#endif
|
||||
|
||||
if(debug_cellnames && pointer_indices.count(c)) {
|
||||
shstream ss; print(ss, c);
|
||||
queuestr(V, .5, ss.s, 0xFFFFFFFF);
|
||||
queuestr(V, mapfontscale / 200, ss.s, 0xFFFFFFFF);
|
||||
queuepoly(V * ddspin(c, 0), cgi.shAsymmetric, darkena(0x000000, 0, 0xC0));
|
||||
}
|
||||
}
|
||||
|
@ -2497,20 +2529,13 @@ void celldrawer::draw_item_full() {
|
|||
if(doHighlight()) asciiborder = kind_outline(it) >> 8;
|
||||
|
||||
if(it == itCompass && isPlayerOn(c)) {
|
||||
cell *c1 = c ? findcompass(c) : NULL;
|
||||
if(c1) {
|
||||
shiftmatrix P = ggmatrix(c1);
|
||||
shiftpoint P1 = tC0(P);
|
||||
|
||||
queuestr(P1, 2*vid.fsize, "X", 0x10100 * int(128 + 100 * sintick(150)));
|
||||
queuestr(P1, vid.fsize, its(-compassDist(c)), 0x10101 * int(128 - 100 * sintick(150)));
|
||||
addauraspecial(P1, 0xFF0000, 0);
|
||||
}
|
||||
shiftpoint dummy;
|
||||
mark_compass(c, dummy);
|
||||
}
|
||||
}
|
||||
|
||||
if(it) {
|
||||
if((c->land == laWhirlwind || c->item == itBabyTortoise || c->land == laWestWall) && c->wall != waBoat) {
|
||||
if(c->wall != waBoat) {
|
||||
double footphase = 0;
|
||||
applyAnimation(c, Vboat, footphase, LAYER_BOAT);
|
||||
}
|
||||
|
@ -2581,7 +2606,7 @@ void celldrawer::draw_monster_full() {
|
|||
bool dm = drawMonster(V, c->type, c, moncol, asciicol);
|
||||
if(dm) onradar = false;
|
||||
#if CAP_SHAPES
|
||||
if(isize(ptds) != q) {
|
||||
if(isize(ptds) != q && !(c == lmouseover_distant && isDie(c->monst))) {
|
||||
if(WDIM == 2 && GDIM == 3 && abs(cgi.SLEV[sl] - cgi.FLOOR) > 1e-6)
|
||||
pushdown(c, q, V, cgi.SLEV[sl] - cgi.FLOOR, false, false);
|
||||
if(GDIM ==2 && abs(geom3::factor_to_lev(zlevel(tC0(Vboat.T)))) > 1e-6)
|
||||
|
@ -2855,7 +2880,7 @@ void celldrawer::draw() {
|
|||
|
||||
if(callhandlers(false, hooks_drawcell, c, V)) return;
|
||||
|
||||
if(history::on || inHighQual || WDIM == 3 || shmup::on || sightrange_bonus > gamerange_bonus || !playermoved) checkTide(c);
|
||||
checkTide(c);
|
||||
|
||||
if(1) {
|
||||
|
||||
|
@ -2962,7 +2987,7 @@ void celldrawer::draw() {
|
|||
string s = s0+asciichar;
|
||||
dynamicval<color_t> p(poly_outline, asciiborder << 8);
|
||||
if(!wmascii3)
|
||||
queuestrn(V, 1, s, darkenedby(asciicol, darken), 2);
|
||||
queuestrn(V, mapfontscale / 100, s, darkenedby(asciicol, darken), 2);
|
||||
else if(highwall(c) && conegraph(c)) {
|
||||
const int layers = 1 << detaillevel;
|
||||
string s1 = s0+asciichar1;
|
||||
|
@ -2970,7 +2995,7 @@ void celldrawer::draw() {
|
|||
for(int z=0; z<layers; z++)
|
||||
queuestrn(orthogonal_move_fol(V, zgrad0(0, geom3::actual_wall_height(), z, layers)), 1. - z * .5 / layers, s1, darkenedby(gradient(bordcolor, asciicol1, -layers, z, layers), darken), 1);
|
||||
poly_outline = asciiborder << 8;
|
||||
queuestrn(orthogonal_move_fol(V, cgi.WALL), asciicol == asciicol1 && asciichar == asciichar1 ? .5 : 1, s, darkenedby(asciicol, darken), 2);
|
||||
queuestrn(orthogonal_move_fol(V, cgi.WALL), (asciicol == asciicol1 && asciichar == asciichar1 ? .5 : 1) * mapfontscale / 100, s, darkenedby(asciicol, darken), 2);
|
||||
}
|
||||
else if(highwall(c)) {
|
||||
const int layers = 1 << detaillevel;
|
||||
|
@ -2979,15 +3004,15 @@ void celldrawer::draw() {
|
|||
for(int z=0; z<layers; z++)
|
||||
queuestrn(orthogonal_move_fol(V, zgrad0(0, geom3::actual_wall_height(), z, layers)), 1, s1, darkenedby(gradient(bordcolor, asciicol1, -layers, z, layers), darken), 1);
|
||||
poly_outline = asciiborder << 8;
|
||||
queuestrn(orthogonal_move_fol(V, cgi.WALL), 1, s, darkenedby(asciicol, darken), 2);
|
||||
queuestrn(orthogonal_move_fol(V, cgi.WALL), mapfontscale / 100, s, darkenedby(asciicol, darken), 2);
|
||||
}
|
||||
else if((sl = snakelevel(c))) {
|
||||
string s1 = s0+asciichar1;
|
||||
poly_outline = bordcolor << 8;
|
||||
for(int z=0; z<sl*4; z++) if(z%4 == 0)
|
||||
queuestrn(orthogonal_move_fol(V, zgrad0(0, cgi.slev * sl, z, sl*4)), 1, s1, darkenedby(gradient(bordcolor, asciicol1, -sl, z, sl*4), darken), 1);
|
||||
queuestrn(orthogonal_move_fol(V, zgrad0(0, cgi.slev * sl, z, sl*4)), mapfontscale / 100, s1, darkenedby(gradient(bordcolor, asciicol1, -sl, z, sl*4), darken), 1);
|
||||
poly_outline = asciiborder << 8;
|
||||
queuestrn(orthogonal_move_fol(V, cgi.SLEV[sl]), 1, s, darkenedby(asciicol, darken), 2);
|
||||
queuestrn(orthogonal_move_fol(V, cgi.SLEV[sl]), mapfontscale / 100, s, darkenedby(asciicol, darken), 2);
|
||||
}
|
||||
// else if(c->wall == waChasm) {
|
||||
// const int layers = 1 << detaillevel;
|
||||
|
@ -2996,12 +3021,12 @@ void celldrawer::draw() {
|
|||
else if(chasmgraph(c)) {
|
||||
string s1 = s0+asciichar1;
|
||||
poly_outline = bordcolor << 8;
|
||||
queuestrn(orthogonal_move_fol(V, cgi.BOTTOM), 1, s1, darkenedby(gradient(bordcolor, asciicol1, 0, 0.3, 1), darken), 2);
|
||||
queuestrn(orthogonal_move_fol(V, cgi.BOTTOM), mapfontscale / 100, s1, darkenedby(gradient(bordcolor, asciicol1, 0, 0.3, 1), darken), 2);
|
||||
poly_outline = asciiborder << 8;
|
||||
queuestrn(V, 1, s, darkenedby(asciicol, darken), 2);
|
||||
queuestrn(V, mapfontscale / 100, s, darkenedby(asciicol, darken), 2);
|
||||
}
|
||||
else
|
||||
queuestrn(V, 1, s, darkenedby(asciicol, darken), 2);
|
||||
queuestrn(V, mapfontscale / 100, s, darkenedby(asciicol, darken), 2);
|
||||
}
|
||||
|
||||
draw_grid();
|
||||
|
|
145
changelog.txt
145
changelog.txt
|
@ -5104,3 +5104,148 @@ Other fixes:
|
|||
- fixed tides in shmup and when scrolling
|
||||
- the dipping rule no longer affects Tiger's Eyes
|
||||
- screenshots were sometimes not correctly centered
|
||||
|
||||
2024-02-23 01:34 Update 13.0b:
|
||||
|
||||
When you are checkmated or die, a message explaining the cause is now displayed in the quit screen and saved in the local score file.
|
||||
|
||||
Crossbow fixes:
|
||||
- opening inventory mode when you can just shoot should be fixed
|
||||
- rusałka curses now work
|
||||
- fixed tricking Pikemen with a bow
|
||||
- while rosed, you can now only shoot when this kills a monster at point blank in the rose direction
|
||||
|
||||
Crash fixes:
|
||||
- fixed crash when e.g. entering 'ma' as a value, or when editing some settings such as sight range bonus
|
||||
- fixed a crash when viewing help on tide tiles (thanks to jlm)
|
||||
- fixed a crash with too large band
|
||||
- fixed some cases where untruncated/unrectified/warped maps would freeze when computing distances or crash due to trees are not known
|
||||
|
||||
Gameplay fixes:
|
||||
- restarting a race now resets pause counter
|
||||
- World Turtle kills are recorded (thanks to jlm)
|
||||
- boat can go thru non-adjacent using Orb of Warp in shmup
|
||||
- fixed the items (key, OoY, baby tortoise) moved by the Orb of Chaos and Curse of Repulsion
|
||||
- fixed the Yard bug (graveless graveyard when you somehow used Orb of Safety in the Haunted Woods strip)
|
||||
- Trollheim no longer generates adjacent non-unlocked troll lands
|
||||
- alternative land unlock rules when monster/item requested is not available due to geometry etc
|
||||
|
||||
Other:
|
||||
- in Goldberg variation, x/y limit is now based on what the engine allows, and 'dual of current' no longer can circumvent the limits
|
||||
- New projection: polar coordinates
|
||||
|
||||
2024-02-24 09:54 Update 13.0c:
|
||||
|
||||
- fixed the off-by-one error in thehelp line displayed for tides and lava
|
||||
- fixed a bug with rusalka-cursing the first tile when you shoot
|
||||
- when you press ESC in the gameover screen, the YASC message is displayed
|
||||
- special YASC message for pinches, and being on the Round Table
|
||||
- in YASC messages, mention the knights blocking the way, and also mention their names
|
||||
|
||||
2024-03-24 11:32 Update 13.0d:
|
||||
|
||||
System:
|
||||
* itch.io Windows binaries and Steam Windows/Linux binaries now use SDL2 instead of SDL1.2
|
||||
|
||||
Custom mode:
|
||||
* A new mode where you can select the lands to be used.
|
||||
* Another menu can be used to save a mode to a file.
|
||||
* Enabling Halloween or Space Rocks in infinite geometries now produces something that makes sense.
|
||||
* Previously changing the creature scale was disabled in non-cheat shmup. Now it can be changed (but it counts as a cheat).
|
||||
* New land structure 'landscape'.
|
||||
|
||||
Graphics:
|
||||
* Font scale used in ASCII maps now can be changed.
|
||||
* Items moved by Orb of Water, Magnetism, Winter, Space, and Repulsion are now animated.
|
||||
* VR: fixed items, Ivy, compasses, etc. being placed incorrectly in 2.5D.
|
||||
* VR: compass/Yendor targets now should be displayed.
|
||||
|
||||
Gameplay:
|
||||
* Void Beasts are now pulled by Orb of Air.
|
||||
* Changed the electrical properties of some walls to make Eclectic City more friendly.
|
||||
* Trees etc are now mentioned as blockers in YASC messages.
|
||||
* YASC codes work better if killed on a 10+ tile.
|
||||
|
||||
Alternate geometries:
|
||||
* Clear more walls when generating Wild West in high GP.
|
||||
* Better Emerald in Octagon chamfered.
|
||||
* Fixed Emerald Mine and Vineyard generating very bad in {n,oo} and binary tiling.
|
||||
* Fixed the lack of non-trapdoors in Zebra 435.
|
||||
* Better 'pseudohept' tiles in INVERSE tilings.
|
||||
* In grid mode, don't try to draw greatwall lines outside of normal geometry pure/bitruncated.
|
||||
* Nicer cell boundaries used in Archimedean and irregular tilings.
|
||||
* When you save an irregular map using Orb of Safety or map editor (or custom mode), it should now save the irregular map used.
|
||||
|
||||
Bug fixes:
|
||||
* Fixed dice hints over different heights.
|
||||
* Fixed troll nests in Horodisk/Voronoi.
|
||||
* Fixed a crash when running away from Clearing in single-land mode.
|
||||
* Some values are tracked in savefiles while previously they did not (fatigue, snake oil, crossbow reload time, gun ammo, etc.) (Thanks to jlm)
|
||||
|
||||
2024-03-24 20:10 Update 13.0e:
|
||||
|
||||
* in Steam, option `-achievement-always` to always display achievements, even if you already got them.
|
||||
* rosebushes now show up on the radar in 3D geometries, and they now blink if they are close to going off
|
||||
* if you are in water (and have no Fish), you can now see Orbs of Fish and Aether in adjacent water tiles, and also you can move there and pick them up
|
||||
* crossbow bolt now ignore rose restrictions on attack
|
||||
* migrating to SDL2 caused crashes in shmup, with the game_keys_scroll option, and with the shift-target option -- this should be fixed
|
||||
* 'custom' land list mode is now mentioned in the watermark (bottom left of the screen)
|
||||
|
||||
2024-03-27 23:47 Update 13.0f:
|
||||
|
||||
* new messages on Orb of Phasing, Slaying, and Weakness
|
||||
* more accurate messages on dice pushing
|
||||
* when loading save, load full mode data including custom lands
|
||||
* irregular maps no longer change on every load due to floating point precision
|
||||
* [custom lands list] Space Rock monsters now drop treasure only if in Space Rock land
|
||||
* ineligible starting land also if land is not in game
|
||||
* [custom lands list] do not freeze if no new sealand is available
|
||||
* in countHyperstones, two variants of Mirror are counted once
|
||||
* specially generated lands (horocycles, Brown Islands) now respect Unlocked and LandIngame rules
|
||||
* fixed some more crashes related to SDL2 (e.g., right-click in shmup)
|
||||
|
||||
2024-04-09 02:46 Update 13.0g:
|
||||
|
||||
- New land structures: CR2-like, CR3-like, and "cursed"
|
||||
- Space Rocks and Halloween stuff are now saved correctly (thanks to jlm)
|
||||
- since the Aether users now see adjacent items in water, they can also pick them up
|
||||
- fixed the bug where moving a boat with Compass would cause items to be picked up
|
||||
- pushing an exploding barrel on a mine now causes an explosion
|
||||
- fixed pressing numpad keys with numpad on acting both as moves and quick-keys
|
||||
- a new pseudoheptagon pattern in standard binary and ternary tiling
|
||||
- fixed the Free Fall being not inaccessible from some lands
|
||||
- auto-pause shmup game when it loses focus
|
||||
- fixed some possible crashes: with keys being generated on ivy, when using Orb of Space on Orb of Safety, Ocean in the chaos modes, after killing 400 mutants, when generating YASC message
|
||||
|
||||
2024-05-09 10:45 Update 13.0h
|
||||
|
||||
- Orb of Summoning now works on deep water, shallow water, and Camelot moat tiles
|
||||
- more settings for minefield graphics
|
||||
- removed Haunted and Elemental from the landscape mode
|
||||
- stone gargoyles and statues are now non-blocking for missiles
|
||||
- Orb of Earth now cancels Invisibility only if it is doing something
|
||||
- new line pattern 'wall highlight', and also line patterns are now easier to reach (via creative mode)
|
||||
- fixed the Yendor beacon to appear in the correct place (usually on the boundary, not the closest visible tile)
|
||||
|
||||
Minor bug fixes:
|
||||
- some leaderboards still activated when custom_land_list was used
|
||||
- fixed CR3 generated in CR2 layout
|
||||
- fixed CR2 generated in CR3/CR4 layouts
|
||||
- fixed single wrong tile of the first land when safetying in landscape etc
|
||||
- fixed 534 distance computation
|
||||
- fixed CLI -picload
|
||||
- clear boats from removed Orbs of Water
|
||||
- fixed a crash setting landscape_div to 0
|
||||
- fixed a crash with irregular spherical maps
|
||||
- show weapon watermark with geometric xbow (thanks to @jlm)
|
||||
|
||||
2024-05-10 19:36 Update 13.0i
|
||||
|
||||
- reverted numlock fix on MAC since it apparently does not work as expected
|
||||
- right shift no longer assumes mouse-strafe if no mouse moved
|
||||
- fixed the "display zeros in minefield" option
|
||||
- fixed crashes when adding/deleting colors
|
||||
- rosewaves no longer go through the fake cells in Crystal World
|
||||
- changed the guarding in Power landscape
|
||||
- display Compass and Orb of Yendor beacon on radar
|
||||
- fixed some problems with tides (thanks to jlm)
|
||||
|
|
165
checkmove.cpp
165
checkmove.cpp
|
@ -27,29 +27,49 @@ EX bool canmove = true;
|
|||
|
||||
// how many monsters are near
|
||||
EX eMonster who_kills_me;
|
||||
EX cell *who_kills_me_cell;
|
||||
|
||||
EX int lastkills;
|
||||
|
||||
EX vector<bool> legalmoves;
|
||||
|
||||
/* why is a move illegal */
|
||||
EX vector<int> move_issues;
|
||||
|
||||
#if HDR
|
||||
struct moveissue {
|
||||
int type;
|
||||
int subtype;
|
||||
eMonster monster;
|
||||
cell *where;
|
||||
};
|
||||
|
||||
static constexpr int miVALID = 10000;
|
||||
static constexpr int miENTITY = 11000;
|
||||
static constexpr int miRESTRICTED = 10100;
|
||||
static constexpr int miTHREAT = 10010;
|
||||
static constexpr int miWALL = 10001;
|
||||
|
||||
static constexpr int siWALL = 1;
|
||||
static constexpr int siMONSTER = 2;
|
||||
static constexpr int siGRAVITY = 3;
|
||||
static constexpr int siROSE = 4;
|
||||
static constexpr int siITEM = 5;
|
||||
static constexpr int siWIND = 6;
|
||||
static constexpr int siCURRENT = 7;
|
||||
static constexpr int siFATIGUE = 8;
|
||||
static constexpr int siWARP = 9;
|
||||
static constexpr int siUNKNOWN = 10;
|
||||
#endif
|
||||
|
||||
EX int checked_move_issue;
|
||||
/* why is a move illegal */
|
||||
EX vector<moveissue> move_issues;
|
||||
|
||||
EX moveissue checked_move_issue;
|
||||
EX moveissue stay_issue;
|
||||
EX int yasc_code;
|
||||
|
||||
EX void check_if_monster() {
|
||||
eMonster m = cwt.peek()->monst;
|
||||
if(m && m != passive_switch && !isFriendly(m))
|
||||
checked_move_issue = miENTITY;
|
||||
checked_move_issue = moveissue { miENTITY, siMONSTER, m, cwt.peek() };
|
||||
}
|
||||
|
||||
EX bool hasSafeOrb(cell *c) {
|
||||
|
@ -108,14 +128,14 @@ EX bool monstersnear(cell *c, eMonster who) {
|
|||
bool kraken_will_destroy_boat = false;
|
||||
|
||||
elec::builder b;
|
||||
if(elec::affected(c)) { who_kills_me = moLightningBolt; res++; }
|
||||
if(elec::affected(c)) { who_kills_me = moLightningBolt; who_kills_me_cell = nullptr; res++; }
|
||||
|
||||
if(c->wall == waArrowTrap && c->wparam == 2) {
|
||||
who_kills_me = moArrowTrap; res++;
|
||||
who_kills_me = moArrowTrap; who_kills_me_cell = nullptr; res++;
|
||||
}
|
||||
|
||||
for(auto c1: crush_now) if(c == c1) {
|
||||
who_kills_me = moCrusher; res++;
|
||||
who_kills_me = moCrusher; who_kills_me_cell = nullptr; res++;
|
||||
}
|
||||
|
||||
if(who == moPlayer || items[itOrbEmpathy]) {
|
||||
|
@ -126,7 +146,7 @@ EX bool monstersnear(cell *c, eMonster who) {
|
|||
if(havewhat&HF_OUTLAW) {
|
||||
for(cell *c1: gun_targets(c))
|
||||
if(c1->monst == moOutlaw && !c1->stuntime) {
|
||||
res++; who_kills_me = moOutlaw;
|
||||
res++; who_kills_me = moOutlaw; who_kills_me_cell = c1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -157,13 +177,11 @@ EX bool monstersnear(cell *c, eMonster who) {
|
|||
}
|
||||
// flashwitches cannot attack if it would kill another enemy
|
||||
if(c3->monst == moWitchFlash && flashWouldKill(c3, 0)) continue;
|
||||
res++, who_kills_me = c3->monst;
|
||||
res++, who_kills_me = c3->monst; who_kills_me_cell = c3;
|
||||
}
|
||||
|
||||
// consider normal monsters
|
||||
if(c2 &&
|
||||
isArmedEnemy(c2, who) &&
|
||||
(c2->monst != moLancer || isUnarmed(who) || !logical_adjacent(c, who, c2))) {
|
||||
if(c2 && isArmedEnemy(c2, who)) {
|
||||
eMonster m = c2->monst;
|
||||
if(elec::affected(c2)) continue;
|
||||
if(fast && c2->monst != moWitchSpeed) continue;
|
||||
|
@ -179,12 +197,12 @@ EX bool monstersnear(cell *c, eMonster who) {
|
|||
eaten = true;
|
||||
else if(c2->monst != moHexSnake) continue;
|
||||
}
|
||||
res++, who_kills_me = m;
|
||||
res++, who_kills_me = m; who_kills_me_cell = c2;
|
||||
}
|
||||
}
|
||||
|
||||
if(kraken_will_destroy_boat && !krakensafe(c) && warningprotection(XLAT("This move appears dangerous -- are you sure?"))) {
|
||||
if (res == 0) who_kills_me = moWarning;
|
||||
if (res == 0) who_kills_me = moWarning; who_kills_me_cell = nullptr;
|
||||
res++;
|
||||
} else {
|
||||
if(who == moPlayer && res && (markOrb2(itOrbShield) || markOrb2(itOrbShell)) && !eaten)
|
||||
|
@ -239,7 +257,7 @@ EX bool monstersnear_aux() {
|
|||
/** like monstersnear but add the potential moves of other players into account */
|
||||
EX bool monstersnear_add_pmi(player_move_info pmi0) {
|
||||
if(suicidal) {
|
||||
who_kills_me = moPlayer;
|
||||
who_kills_me = moPlayer; who_kills_me_cell = nullptr;
|
||||
return true;
|
||||
}
|
||||
pmi.push_back(pmi0);
|
||||
|
@ -280,6 +298,110 @@ EX bool swordConflict(const player_move_info& sm1, const player_move_info& sm2)
|
|||
return false;
|
||||
}
|
||||
|
||||
EX string yasc_message;
|
||||
|
||||
EX string blocking_monster_name(const moveissue& mi) {
|
||||
if(mi.monster == moKnight && mi.where)
|
||||
return XLAT("%1 the Knight", camelot::knight_name(mi.where));
|
||||
else
|
||||
return dnameof(mi.monster);
|
||||
}
|
||||
|
||||
EX void create_yasc_message() {
|
||||
set<pair<cell*, string>> captures;
|
||||
auto all = move_issues;
|
||||
all.push_back(stay_issue);
|
||||
for(auto c: all) if(c.type == miTHREAT) captures.emplace(c.where, blocking_monster_name(c));
|
||||
|
||||
vector<string> context;
|
||||
if(!captures.empty()) {
|
||||
string msg = "captured by ";
|
||||
map<string, int> qties;
|
||||
for(auto ca: captures) qties[ca.second]++;
|
||||
int iqties = 0;
|
||||
for(auto q: qties) {
|
||||
if(iqties && iqties == isize(qties) - 1) msg += " and ";
|
||||
else if(iqties) msg += ", ";
|
||||
msg += q.first;
|
||||
if(q.second > 1) msg += " (x" + its(q.second) + ")";
|
||||
iqties++;
|
||||
}
|
||||
context.push_back(msg);
|
||||
}
|
||||
|
||||
int idx = 0;
|
||||
for(auto c: all) if(idx == 0 && c.subtype == siROSE) context.push_back("rosed"), idx = 1;
|
||||
for(auto c: all) if(idx < 2 && c.subtype == siWIND) context.push_back("blown away"), idx = 2;
|
||||
for(auto c: all) if(idx < 3 && c.subtype == siGRAVITY) context.push_back("falling"), idx = 3;
|
||||
for(auto c: all) if(idx < 4 && c.subtype == siFATIGUE) context.push_back("fatigued"), idx = 4;
|
||||
for(auto c: all) if(idx < 5 && c.subtype == siCURRENT) context.push_back("whirled"), idx = 5;
|
||||
|
||||
bool in_ctx = true;
|
||||
|
||||
set<string> blocks;
|
||||
int index = 0;
|
||||
for(auto c: all) {
|
||||
if(c.type == miENTITY && !captures.count({c.where, blocking_monster_name(c)})) blocks.insert(blocking_monster_name(c));
|
||||
else if(c.type == miWALL && c.subtype == siMONSTER && !captures.count({c.where, blocking_monster_name(c)})) blocks.insert(blocking_monster_name(c));
|
||||
else if(c.subtype == siITEM) blocks.insert("item");
|
||||
else if(c.subtype == siWALL) {
|
||||
if(c.where == cwt.at) {
|
||||
if(in_ctx) {
|
||||
if(c.where->wall == waNone && c.where->land == laBrownian)
|
||||
context.push_back("on level 3");
|
||||
else if(c.where->wall == waRoundTable)
|
||||
context.push_back("being polite");
|
||||
else
|
||||
context.push_back(winf[c.where->wall].flags & WF_ON ? XLAT("on %the1", c.where->wall) : XLAT("in %the1", c.where->wall));
|
||||
}
|
||||
in_ctx = false;
|
||||
}
|
||||
else if(c.where && c.where->wall != cwt.at->wall) blocks.insert(dnameof(c.where->wall));
|
||||
}
|
||||
else if(c.type == siWARP) blocks.insert("warp");
|
||||
index++;
|
||||
}
|
||||
|
||||
if(!blocks.empty()) {
|
||||
string block = "blocked by ";
|
||||
int iqties = 0;
|
||||
for(auto& q: blocks) {
|
||||
if(iqties && iqties == isize(blocks) - 1) block += " and ";
|
||||
else if(iqties) block += ", ";
|
||||
block += q;
|
||||
iqties++;
|
||||
}
|
||||
context.push_back(block);
|
||||
}
|
||||
|
||||
yasc_message = "";
|
||||
int iqties = 0;
|
||||
for(auto& ctx: context) {
|
||||
if(iqties == 0) ;
|
||||
else if(iqties == 1) yasc_message += " while ";
|
||||
else if(iqties == isize(context) - 1) yasc_message += " and ";
|
||||
else yasc_message += ", ";
|
||||
yasc_message += ctx;
|
||||
iqties++;
|
||||
}
|
||||
|
||||
if(captures.size() == 2 && context.size() == 1 && cwt.at->type == 6) {
|
||||
vector<int> dirs;
|
||||
forCellIdEx(c1, i, cwt.at) for(auto cap: captures) if(cap.first == c1) dirs.push_back(i);
|
||||
if(isize(dirs) == 2 && abs(dirs[0]-dirs[1]) == 3) {
|
||||
auto c1 = captures.begin(); c1++;
|
||||
yasc_message = XLAT("pinched by %the1 and %the2", captures.begin()->second, c1->second);
|
||||
}
|
||||
}
|
||||
|
||||
println(hlog, "YASC_MESSAGE: ", yasc_message);
|
||||
}
|
||||
|
||||
int yasc_recode(int x) {
|
||||
if(cwt.at->type < 10 || x == 0) return x;
|
||||
return yasc_recode(x / 10) * 100 + (x % 10);
|
||||
};
|
||||
|
||||
EX void checkmove() {
|
||||
|
||||
if(dual::state == 2) return;
|
||||
|
@ -295,12 +417,13 @@ EX void checkmove() {
|
|||
if(hardcore) return;
|
||||
|
||||
legalmoves.clear(); legalmoves.resize(cwt.at->type+1, false);
|
||||
move_issues.clear(); move_issues.resize(cwt.at->type, 0);
|
||||
move_issues.clear(); move_issues.resize(cwt.at->type);
|
||||
|
||||
canmove = haveRangedTarget();
|
||||
items[itWarning]+=2;
|
||||
if(movepcto(-1, 0, true))
|
||||
canmove = legalmoves[cwt.at->type] = true;
|
||||
stay_issue = checked_move_issue;
|
||||
|
||||
if(true) {
|
||||
for(int i=0; i<cwt.at->type; i++) {
|
||||
|
@ -323,7 +446,9 @@ EX void checkmove() {
|
|||
|
||||
yasc_code = 0;
|
||||
for(int i=0; i<cwt.at->type; i++)
|
||||
yasc_code += move_issues[i];
|
||||
yasc_code += yasc_recode(move_issues[i].type);
|
||||
|
||||
if(!canmove && bow::crossbow_mode() && !items[itCrossbow]) canmove = bow::have_bow_target();
|
||||
|
||||
#if CAP_INV
|
||||
if(inv::on && !canmove && !inv::incheck) {
|
||||
|
@ -339,12 +464,12 @@ EX void checkmove() {
|
|||
}
|
||||
#endif
|
||||
|
||||
if(!canmove && bow::crossbow_mode() && !items[itCrossbow]) canmove = bow::have_bow_target();
|
||||
|
||||
if(!canmove) {
|
||||
create_yasc_message();
|
||||
achievement_final(true);
|
||||
if(cmode & sm::NORMAL) showMissionScreen();
|
||||
}
|
||||
else yasc_message = "";
|
||||
|
||||
if(canmove && timerstopped) {
|
||||
timerstart = time(NULL);
|
||||
|
|
|
@ -601,6 +601,7 @@ static constexpr flagtype WF_CISLAND = Flag(19);
|
|||
static constexpr flagtype WF_SULPHURIC = Flag(20);
|
||||
static constexpr flagtype WF_HALFVINE = Flag(21);
|
||||
static constexpr flagtype WF_NONBLOCK = Flag(22);
|
||||
static constexpr flagtype WF_ON = Flag(23); // just for grammar: 'on' not 'in'
|
||||
|
||||
struct walltype {
|
||||
char glyph;
|
||||
|
@ -1031,7 +1032,7 @@ enum eModel : int {
|
|||
// 39..48
|
||||
mdPoorMan, mdPanini, mdRetroCraig, mdRetroLittrow, mdRetroHammer, mdThreePoint, mdLiePerspective, mdLieOrthogonal, mdRelPerspective, mdRelOrthogonal,
|
||||
// 49..50
|
||||
mdHorocyclicEqa, mdConformalSquare, mdFisheye2,
|
||||
mdHorocyclicEqa, mdConformalSquare, mdFisheye2, mdPolar,
|
||||
// 51..
|
||||
mdGUARD, mdPixel, mdHyperboloidFlat, mdPolynomial, mdManual
|
||||
};
|
||||
|
@ -1096,6 +1097,7 @@ EX vector<modelinfo> mdinf = {
|
|||
{X3("horocyclic equal-area"), mf::euc_boring | mf::equiarea | mf::orientation | mf::horocyclic},
|
||||
{X3("conformal square"), mf::orientation | mf::broken | mf::transition},
|
||||
{X3("variant fisheye"), 0},
|
||||
{X3("polar coordinates"), mf::orientation},
|
||||
{X3("guard"), mf::technical},
|
||||
{X3("pixel"), mf::technical},
|
||||
{X3("hypflat"), mf::technical},
|
||||
|
|
|
@ -335,6 +335,19 @@ int arg::readCommon() {
|
|||
clearMessages();
|
||||
}
|
||||
|
||||
else if(argis("-save-mode")) {
|
||||
save_mode_to_file(shift_args());
|
||||
}
|
||||
|
||||
else if(argis("-load-mode")) {
|
||||
try {
|
||||
load_mode_from_file(shift_args());
|
||||
}
|
||||
catch(hstream_exception& e) {
|
||||
println(hlog, "exception!");
|
||||
}
|
||||
}
|
||||
|
||||
// informational
|
||||
else if(argis("-version") || argis("-v")) {
|
||||
printf("HyperRogue version " VER "\n");
|
||||
|
|
13
complex.cpp
13
complex.cpp
|
@ -215,10 +215,14 @@ EX namespace elec {
|
|||
if(c->wall == waSea || c->wall == waGrounded) return ecGrounded;
|
||||
if(c->wall == waSandstone || c->wall == waDeadTroll ||
|
||||
c->wall == waDeadTroll2 ||
|
||||
among(c->wall, waBigTree, waSmallTree, waExplosiveBarrel, waRed1, waRed2, waRed3) ||
|
||||
c->wall == waExplosiveBarrel ||
|
||||
c->wall == waVinePlant ||
|
||||
c->wall == waMetal || isAlchAny(c))
|
||||
return isElectricLand(c) ? ecConductor : ecGrounded;
|
||||
if(c->wall == waBigTree || c->wall == waSmallTree)
|
||||
return ecGrounded;
|
||||
if(among(c->wall, waRed1, waRed2, waRed3, waRubble, waDeadfloor2))
|
||||
return ecIsolator;
|
||||
if(c->wall == waBarrier)
|
||||
return ecIsolator;
|
||||
if(c->wall == waChasm)
|
||||
|
@ -644,7 +648,7 @@ struct info {
|
|||
if(newdist == OUT_OF_PRISON && princess::challenge) {
|
||||
addMessage(XLAT("Congratulations! Your score is %1.", its(i->value)));
|
||||
achievement_gain_once("PRINCESS2", rg::princess);
|
||||
if(!cheater) achievement_score(36, i->value);
|
||||
if(!cheater) achievement_score(LB_PRINCESS, i->value);
|
||||
LATE( showMissionScreen(); )
|
||||
}
|
||||
}
|
||||
|
@ -2126,6 +2130,8 @@ EX namespace heat {
|
|||
if(c->monst == moDesertman) hmod += 4 * xrate;
|
||||
if(c->monst == moAngryDie) hmod += 4 * xrate;
|
||||
if(c->monst == moMonkey) hmod += xrate;
|
||||
if(c->wall == waCharged) hmod += xrate * .25;
|
||||
if(c->wall == waGrounded) hmod -= xrate * .25;
|
||||
if(c->wall == waDeadTroll) hmod -= 2 * xrate;
|
||||
if(c->wall == waDeadTroll2) hmod -= 1.5 * xrate;
|
||||
if(c->wall == waBigStatue) hmod -= .5 * xrate;
|
||||
|
@ -2478,7 +2484,9 @@ EX void livecaves() {
|
|||
if(hv > 0 && c->wall == waNone) {
|
||||
if(c->item && c->cpdist == 1 && markOrb(itOrbWater)) {
|
||||
bool saf = c->item == itOrbSafety;
|
||||
eItem it = c->item;
|
||||
collectItem(c, c);
|
||||
if(it && !c->item) animate_item_throw(c, cwt.at, it);
|
||||
if(saf) return;
|
||||
}
|
||||
c->wall = waSea;
|
||||
|
@ -3498,6 +3506,7 @@ EX namespace ca {
|
|||
}
|
||||
for(int i=0; i<dcs; i++) {
|
||||
cell *c = allcells[i];
|
||||
if(c->land != laCA) continue;
|
||||
auto last = c->wall;
|
||||
c->wall = willlive[i] ? wlive : waNone;
|
||||
if(c->wall != last) {
|
||||
|
|
10
complex2.cpp
10
complex2.cpp
|
@ -166,11 +166,11 @@ EX namespace brownian {
|
|||
ONEMPTY {
|
||||
if(hrand(10000) < min(250, 100 + 2 * PT(kills[moAcidBird] + kills[moBrownBug], 50)) * (25 + min(items[itBrownian], 100)) / 25 && c->landparam >= 4 && c->landparam < 24)
|
||||
c->item = itBrownian;
|
||||
if(hrand_monster(8000) < 15 + items[itBrownian])
|
||||
if(hrand_monster_in(laBrownian, 8000) < 15 + items[itBrownian])
|
||||
c->monst = moAcidBird;
|
||||
else if(hrand_monster(8000) < 15)
|
||||
else if(hrand_monster_in(laBrownian, 8000) < 15)
|
||||
c->monst = moAlbatross;
|
||||
else if(hrand_monster(8000) < 15 + items[itBrownian]) {
|
||||
else if(hrand_monster_in(laBrownian, 8000) < 15 + items[itBrownian]) {
|
||||
c->monst = moBrownBug;
|
||||
c->hitpoints = 3;
|
||||
}
|
||||
|
@ -291,7 +291,7 @@ extern array<feature, 21> features;
|
|||
|
||||
#define VF [] (cell *c)
|
||||
|
||||
bool hrand_var(int i) { return hrand_monster(i) < 25 + items[itVarTreasure] + yendor::hardness(); }
|
||||
bool hrand_var(int i) { return hrand_monster_in(laVariant, i) < 25 + items[itVarTreasure] + yendor::hardness(); }
|
||||
|
||||
array<feature, 21> features {{
|
||||
feature{(color_t)(-0x202020), 5, moNecromancer, VF {
|
||||
|
@ -354,6 +354,8 @@ vector<string> knight_names = {
|
|||
"JeLomun", "kip", "Warmonger", "Fooruman", "Zyalin", "Prezombie", "ashley89", "bjobae", "MFErtre", "Roaringdragon2", "howilovepi", "Yulgash", "Sir Endipitous", "Roshlev",
|
||||
"BTernaryTau", "HiGuy", "coper", "Tirear", "qoala _", "Tyzone", "Tiegon", "Airin", "Metroid26", "Sklorg", "Fumblestealth", "Toph", "Tzaphqiel", "jruderman", "ray",
|
||||
"Deathroll", "Sinquetica", "mootmoot", "Noobinator", "freeofme", "Helyea", "Snakebird Priestess", "brisingre", "Khashishi", "Shiny", "kabado", "Berenthas", "Misery", "Altripp", "Aldrenean",
|
||||
// via itch.io and reports on Discord
|
||||
"AntiRogue"
|
||||
};
|
||||
|
||||
map<cell*, int> knight_id;
|
||||
|
|
101
config.cpp
101
config.cpp
|
@ -169,6 +169,7 @@ template<class T> struct enum_setting : list_setting {
|
|||
needs_confirm = true;
|
||||
return this;
|
||||
}
|
||||
virtual cld get_cld() override { return get_value(); }
|
||||
};
|
||||
|
||||
/** transmatrix with equality, so we can construct val_setting<matrix_eq> */
|
||||
|
@ -340,6 +341,8 @@ struct custom_setting : public setting {
|
|||
function<void(char)> custom_viewer;
|
||||
function<cld()> custom_value;
|
||||
function<bool(void*)> custom_affect;
|
||||
function<void(const string&)> custom_load;
|
||||
|
||||
void show_edit_option(int key) override { custom_viewer(key); }
|
||||
supersaver *make_saver() override { throw hr_exception("make_saver for custom_setting"); }
|
||||
bool affects(void *v) override { return custom_affect(v); }
|
||||
|
@ -349,6 +352,15 @@ struct custom_setting : public setting {
|
|||
add_to_changed(this);
|
||||
}
|
||||
}
|
||||
virtual void load_from(const string& s) override {
|
||||
if(saver) { saver->load(s); return; }
|
||||
if(!custom_load) {
|
||||
println(hlog, "cannot load parameter: ", parameter_name, " from: ", s);
|
||||
throw hr_exception("parameter cannot be loaded");
|
||||
}
|
||||
custom_load(s);
|
||||
}
|
||||
virtual cld get_cld() override { return custom_value(); }
|
||||
};
|
||||
|
||||
struct local_parameter_set {
|
||||
|
@ -832,6 +844,7 @@ custom_setting* param_custom(T& val, const string& s, function<void(char)> menui
|
|||
u->custom_viewer = menuitem;
|
||||
u->custom_value = [&val] () { return (int) val; };
|
||||
u->custom_affect = [&val] (void *v) { return &val == v; };
|
||||
u->custom_load = [&val] (const string& s) { val = (T) parseint(s); };
|
||||
u->default_key = key;
|
||||
u->is_editable = true;
|
||||
auto f = &*u;
|
||||
|
@ -1015,6 +1028,8 @@ EX void savecolortable(colortable& ct, string name) {
|
|||
|
||||
EX purehookset hooks_configfile;
|
||||
|
||||
EX ld mapfontscale = 100;
|
||||
|
||||
EX void initConfig() {
|
||||
|
||||
// basic config
|
||||
|
@ -1035,8 +1050,8 @@ EX void initConfig() {
|
|||
param_f(linepatterns::tree_starter, "tree_starter")
|
||||
-> editable(0, 1, 0.05, "tree-drawing parameter", "How much of edges to draw for tree patterns (to show how the tree edges are oriented).", 't');
|
||||
|
||||
param_char(patterns::whichCanvas, "whichCanvas", 0);
|
||||
param_i(patterns::rwalls, "randomwalls");
|
||||
// param_char(patterns::whichCanvas, "whichCanvas", 0); %TODO
|
||||
param_i(ccolor::rwalls, "randomwalls");
|
||||
|
||||
param_b(vid.grid, "grid");
|
||||
param_b(models::desitter_projections, "desitter_projections", false);
|
||||
|
@ -1067,6 +1082,13 @@ EX void initConfig() {
|
|||
-> set_reaction(compute_fsize)
|
||||
-> set_sets([] { dialog::bound_low(0); });
|
||||
|
||||
param_f(mapfontscale, "mapfontscale", 100)
|
||||
-> editable(-400, 400, 10, "map font scale",
|
||||
"This affects the size of the characters on the ASCII map. This includes ASCII walls/monster display mode, the minimap, minefield values, and various debug features.", 'B')
|
||||
->set_extra([] {
|
||||
dialog::get_di().extra_options = [] () { draw_radar(true); };
|
||||
});
|
||||
|
||||
param_i(vid.abs_fsize, "fsize", 12)
|
||||
-> editable(1, 72, 1, "font size", "", 'b')
|
||||
-> set_reaction(compute_fsize)
|
||||
|
@ -1151,6 +1173,8 @@ EX void initConfig() {
|
|||
|
||||
param_i(min_cells_drawn, "min_cells_drawn");
|
||||
|
||||
param_b(show_turns, "show_turns", false)
|
||||
-> editable("show turn count", 'T');
|
||||
param_i(menu_darkening, "menu_darkening", 2)
|
||||
-> editable(0, 8, 1, "menu map darkening", "A larger number means darker game map in the background. Set to 8 to disable the background.", 'd')
|
||||
-> set_sets([] { dialog::bound_low(0); dialog::bound_up(8); dialog::get_di().dialogflags |= sm::DARKEN; });
|
||||
|
@ -1325,7 +1349,7 @@ EX void initConfig() {
|
|||
->set_extra(draw_crosshair);
|
||||
|
||||
param_b(mapeditor::drawplayer, "drawplayer");
|
||||
param_color((color_t&) patterns::canvasback, "color:canvasback", false);
|
||||
param_color((color_t&) ccolor::plain.ctab[0], "color:canvasback", false);
|
||||
|
||||
param_color(backcolor, "color:background", false);
|
||||
param_color(forecolor, "color:foreground", false);
|
||||
|
@ -1337,8 +1361,8 @@ EX void initConfig() {
|
|||
param_color(stdgridcolor, "color:stdgrid", true);
|
||||
param_f(vid.multiplier_grid, "mgrid", "mult:grid", 1);
|
||||
param_color(dialog::dialogcolor, "color:dialog", false);
|
||||
for(auto& p: colortables)
|
||||
savecolortable(p.second, s0+"canvas"+p.first);
|
||||
for(auto p: ccolor::all)
|
||||
savecolortable(p->ctab, s0+"canvas:"+p->name);
|
||||
savecolortable(distcolors, "distance");
|
||||
savecolortable(minecolors, "mines");
|
||||
#if CAP_COMPLEX2
|
||||
|
@ -1366,7 +1390,7 @@ EX void initConfig() {
|
|||
addsaverenum(variation, "mode-variation", eVariation::bitruncated);
|
||||
addsaver(peace::on, "mode-peace");
|
||||
addsaver(peace::otherpuzzles, "mode-peace-submode");
|
||||
addsaverenum(specialland, "land for special modes");
|
||||
param_enum(specialland, "specialland", "land for special modes", specialland);
|
||||
|
||||
addsaver(viewdists, "expansion mode");
|
||||
param_f(backbrightness, "back", "brightness behind sphere");
|
||||
|
@ -1650,6 +1674,18 @@ EX void initConfig() {
|
|||
|
||||
param_i(stamplen, "stamplen");
|
||||
param_f(anims::period, "animperiod");
|
||||
|
||||
addsaver(use_custom_land_list, "customland_use");
|
||||
for(int i=0; i<landtypes; i++) {
|
||||
custom_land_list[i] = true;
|
||||
custom_land_treasure[i] = 100;
|
||||
custom_land_difficulty[i] = 100;
|
||||
custom_land_wandering[i] = 100;
|
||||
addsaver(custom_land_list[i], "customland" + its(i) + "i", true);
|
||||
addsaver(custom_land_treasure[i], "customland" + its(i) + "t", 100);
|
||||
addsaver(custom_land_difficulty[i], "customland" + its(i) + "d", 100);
|
||||
addsaver(custom_land_wandering[i], "customland" + its(i) + "w", 100);
|
||||
}
|
||||
}
|
||||
|
||||
EX bool inSpecialMode() {
|
||||
|
@ -2211,6 +2247,7 @@ EX void showGraphConfig() {
|
|||
add_edit(vid.fontscale);
|
||||
else
|
||||
add_edit(vid.abs_fsize);
|
||||
add_edit(mapfontscale);
|
||||
|
||||
dialog::addSelItem(XLAT("vector settings"), XLAT("width") + " " + fts(vid.linewidth), 'w');
|
||||
dialog::add_action_push(show_vector_settings);
|
||||
|
@ -2408,6 +2445,7 @@ EX void configureInterface() {
|
|||
};
|
||||
});
|
||||
|
||||
add_edit(show_turns);
|
||||
add_edit(menu_darkening);
|
||||
add_edit(centered_menus);
|
||||
add_edit(startanims::enabled);
|
||||
|
@ -2920,8 +2958,7 @@ EX void show3D() {
|
|||
dialog::addSelItem(XLAT("3D detailed settings"), "", 'D');
|
||||
dialog::add_action_push(show3D_height_details);
|
||||
|
||||
if(scale_used())
|
||||
add_edit(vid.creature_scale);
|
||||
add_edit(vid.creature_scale);
|
||||
}
|
||||
else {
|
||||
add_edit(vid.creature_scale);
|
||||
|
@ -3070,7 +3107,9 @@ EX int config3 = addHook(hooks_configfile, 100, [] {
|
|||
}, "context help", 'H');
|
||||
|
||||
param_f(vid.creature_scale, "creature_scale", "3d-creaturescale", 1)
|
||||
->editable(0, 1, .1, "Creature scale", "", 'C');
|
||||
->editable(0, 1, .1, "Creature scale", "", 'C')
|
||||
->set_extra([] { dialog::addInfo(XLAT("changing this during shmup is counted as cheating")); })
|
||||
->set_reaction([] { if(shmup::on) cheater++; });
|
||||
param_f(vid.height_width, "heiwi", "3d-heightwidth", 1.5)
|
||||
->editable(0, 1, .1, "Height to width", "", 'h');
|
||||
param_f(vid.yshift, "yshift", "Y shift", 0)
|
||||
|
@ -3085,7 +3124,15 @@ EX int config3 = addHook(hooks_configfile, 100, [] {
|
|||
param_b(vid.fixed_yz, "fixed YZ", true);
|
||||
param_b(frustum_culling, "frustum_culling");
|
||||
param_b(numerical_minefield, "numerical_minefield")
|
||||
->editable("display mine counts numerically", 'n');
|
||||
-> editable("toggle numerical display", 'n');
|
||||
param_b(mine_hollow, "mine_hollow")
|
||||
-> editable("hollow mine symbols", 'h');
|
||||
param_b(mine_markers, "mine_markers")
|
||||
-> editable("markers on possible mines", 'm');
|
||||
param_i(mine_opacity, "minefield opacity", 255)
|
||||
->editable(0, 255, 51, "opacity of undiscovered minefield", "3D modes only\n\n0 = invisible, 255 = fully opaque", 'o');
|
||||
param_enum(mine_zero_display, "minefield_zero", "minefield_zero", 1)
|
||||
->editable({{"OFF", "never display zeros"}, {"3D", "only in 3D modes"}, {"ON", "always display zeros"}}, "display zeros in minefield", 'z');
|
||||
param_b(dont_display_minecount, "dont_display_minecount");
|
||||
#if MAXMDIM >= 4
|
||||
param_enum(draw_sky, "draw_sky", "draw_sky", skyAutomatic)
|
||||
|
@ -3295,7 +3342,19 @@ EX int config3 = addHook(hooks_configfile, 100, [] {
|
|||
"larger values might produce horodisks with errors or crashing into each other.", 'H');
|
||||
param_i(randomwalk_size, "randomwalk_size", 10)->editable(2, 100, 1,
|
||||
"land size in randomwalk mode",
|
||||
"The average size of a land in randomwalk mode.", 'R');
|
||||
"The average size of a land in randomwalk mode.", 'R')
|
||||
->set_reaction([] { if(game_active) { stop_game(); start_game(); } });
|
||||
param_i(landscape_div, "landscape_div")->editable(1, 100, 1,
|
||||
"land size in landscape structure",
|
||||
"Each cell gets three coordinates, each of which change smoothly, using the same method as used for the generation of landscapes e.g. in Dragon Chasms. "
|
||||
"Then, we find a cell of the bitruncated cubic honeycomb at these cordinates, and this cell determines which land it is. The bigger the value, the larger the lands.", 'R')
|
||||
->set_sets([] { dialog::bound_low(1); })
|
||||
->set_reaction([] { if(game_active) { stop_game(); start_game(); } });
|
||||
|
||||
param_i(curse_percentage, "curse_percentage")->editable(0, 100, 1,
|
||||
"curse percentage",
|
||||
"The percentage of towers in Cursed Walls mode to be manned by Canyon Hags", 'R')
|
||||
->set_reaction([] { if(game_active) { stop_game(); start_game(); } });
|
||||
|
||||
param_f(global_boundary_ratio, "global_boundary_ratio")
|
||||
->editable(0, 5, 0.1, "Width of cell boundaries",
|
||||
|
@ -3408,7 +3467,7 @@ EX void refresh_canvas() {
|
|||
int at = 0;
|
||||
while(at < isize(cl.lst)) {
|
||||
cell *c2 = cl.lst[at];
|
||||
c2->landparam = patterns::generateCanvas(c2);
|
||||
c2->landparam = ccolor::generateCanvas(c2);
|
||||
at++;
|
||||
|
||||
forCellEx(c3, c2) cl.add(c3);
|
||||
|
@ -3430,8 +3489,8 @@ EX void edit_color_table(colortable& ct, const reaction_t& r IS(reaction_t()), b
|
|||
ct[i] ^= 0x1000000;
|
||||
if(!(ct[i] & 0x1000000)) return;
|
||||
}
|
||||
dialog::openColorDialog(ct[i]);
|
||||
dialog::get_di().reaction = r;
|
||||
dialog::openColorDialog(ct[i]);
|
||||
if(r) dialog::get_di().reaction = r;
|
||||
dialog::colorAlpha = false;
|
||||
dialog::get_di().dialogflags |= sm::SIDE;
|
||||
});
|
||||
|
@ -3440,14 +3499,14 @@ EX void edit_color_table(colortable& ct, const reaction_t& r IS(reaction_t()), b
|
|||
dialog::addItem("add a color", 'A');
|
||||
dialog::add_action([&ct, r] {
|
||||
ct.push_back(rand() & 0x1FFFFFF);
|
||||
r();
|
||||
if(r) r();
|
||||
});
|
||||
|
||||
if(isize(ct) > 2) {
|
||||
dialog::addItem("delete a color", 'D');
|
||||
dialog::add_action([&ct, r] {
|
||||
ct.pop_back();
|
||||
r();
|
||||
if(r) r();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -3499,13 +3558,13 @@ EX void show_color_dialog() {
|
|||
dialog::add_action([] () { dialog::openColorDialog(dialog::dialogcolor); dialog::colorAlpha = false; dialog::get_di().dialogflags |= sm::SIDE; });
|
||||
|
||||
dialog::addBreak(50);
|
||||
if(specialland == laCanvas && colortables.count(patterns::whichCanvas)) {
|
||||
if(specialland == laCanvas && ccolor::which->ctab.size()) {
|
||||
dialog::addItem(XLAT("pattern colors"), 'P');
|
||||
dialog::add_action_push([] { edit_color_table(colortables[patterns::whichCanvas], refresh_canvas, true); });
|
||||
dialog::add_action_push([] { edit_color_table(ccolor::which->ctab, refresh_canvas, true); });
|
||||
|
||||
if(patterns::whichCanvas == 'R') {
|
||||
if(ccolor::which == &ccolor::shape_mirror) {
|
||||
dialog::addItem(XLAT("unreversed colors"), 'U');
|
||||
dialog::add_action_push([] { edit_color_table(colortables['A'], refresh_canvas, true); });
|
||||
dialog::add_action_push([] { edit_color_table(ccolor::shape.ctab, refresh_canvas, true); });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3922,7 +3981,7 @@ EX int read_color_args() {
|
|||
PHASEFROM(2); shift(); modelcolor = argcolor(32);
|
||||
}
|
||||
else if(argis("-apeirocolor")) {
|
||||
PHASEFROM(2); shift(); patterns::apeirogonal_color = argcolor(32);
|
||||
PHASEFROM(2); shift(); ccolor::apeirogonal_color = argcolor(32);
|
||||
}
|
||||
else if(argis("-ring")) {
|
||||
PHASEFROM(2); shift(); ringcolor = argcolor(32);
|
||||
|
|
129
content.cpp
129
content.cpp
|
@ -873,8 +873,8 @@ WALL( '#', 0x8080FF, "ice wall", waIcewall, WF_WALL | WF_HIGHWALL | WF_HEATCOLOR
|
|||
"Ice Walls melt after some time has passed."
|
||||
)
|
||||
WALL( '#', 0xC06000, "great wall", waBarrier, WF_WALL | WF_HIGHWALL, RESERVED, 0, sgNone, barrierhelp)
|
||||
WALL( '+', 0x900030, "red slime", waFloorA, ZERO | WF_ALCHEMY, RESERVED, 0, sgFloorA, slimehelp )
|
||||
WALL( '+', 0x300090, "blue slime", waFloorB, ZERO | WF_ALCHEMY, RESERVED, 0, sgFloorB, slimehelp )
|
||||
WALL( '+', 0x900030, "red slime", waFloorA, ZERO | WF_ALCHEMY | WF_ON, RESERVED, 0, sgFloorA, slimehelp )
|
||||
WALL( '+', 0x300090, "blue slime", waFloorB, ZERO | WF_ALCHEMY | WF_ON, RESERVED, 0, sgFloorB, slimehelp )
|
||||
WALL( '#', 0xA0D0A0, "living wall", waCavewall, WF_WALL | WF_HIGHWALL, RESERVED, 0, sgCave, cavehelp)
|
||||
WALL( '.', 0x306060, "living floor", waCavefloor, ZERO, RESERVED, 0, sgNone,cavehelp)
|
||||
WALL( '#', 0xD03030, "dead rock troll", waDeadTroll, WF_WALL | WF_HIGHWALL, RESERVED, 0, sgNone, trollhelp)
|
||||
|
@ -888,7 +888,7 @@ WALL( '%', 0xFFC0C0, "Cloud of Mirage", waCloud, WF_WALL, RESERVED, 0, sgNone,
|
|||
"Tiny droplets of magical water. You see images of yourself inside them. "
|
||||
"Go inside the cloud, to make these images help you.")
|
||||
WALL( '^', 0x8D694F, "Thumper", waThumperOff, WF_WALL | WF_ACTIVABLE | WF_THUMPER, RESERVED, 0, sgNone, thumpdesc)
|
||||
WALL( '^', 0x804000, "Fire", waFire, WF_FIRE | WF_TIMEOUT, RESERVED, 0, sgNone,
|
||||
WALL( '^', 0x804000, "Fire", waFire, WF_FIRE | WF_TIMEOUT | WF_ON, RESERVED, 0, sgNone,
|
||||
"This cell is on fire. Most beings and items cannot survive."
|
||||
)
|
||||
WALL( '+', 0xC0C0C0, "ancient grave", waAncientGrave, WF_WALL | WF_HIGHWALL | WF_GRAVE | WF_NONBLOCK, RESERVED, 0, sgNone,
|
||||
|
@ -917,10 +917,10 @@ WALL( '#', 0x006000, "tree", waSmallTree, WF_WALL | WF_HIGHWALL | WF_STDTREE | W
|
|||
WALL( '#', 0x421C52*2, "vine", waVinePlant, WF_WALL | WF_HIGHWALL, RESERVED, 0, sgVine, vinehelp)
|
||||
WALL( ':', 0x006000, "vine", waVineHalfA, ZERO | WF_NOFLIGHT | WF_HALFVINE, RESERVED, 0, sgVine, hvinehelp)
|
||||
WALL( ';', 0x006000, "vine", waVineHalfB, ZERO | WF_NOFLIGHT | WF_HALFVINE, RESERVED, 0, sgVine, hvinehelp)
|
||||
WALL( '^', 0x804000, "partial fire", waPartialFire, WF_FIRE | WF_TIMEOUT, RESERVED, 0, sgNone, "This cell is partially on fire.")
|
||||
WALL( '#', 0xA07070, "dead wall", waDeadwall, WF_WALL | WF_HIGHWALL, RESERVED, 0, sgCave, deadcavehelp)
|
||||
WALL( '.', 0x401010, "dead floor", waDeadfloor, ZERO, RESERVED, 0, sgNone,deadcavehelp)
|
||||
WALL( '.', 0x905050, "rubble", waDeadfloor2, ZERO, RESERVED, 1, sgNone, "Dead floor, with some rubble.")
|
||||
WALL( '^', 0x804000, "partial fire", waPartialFire, WF_FIRE | WF_TIMEOUT | WF_ON, RESERVED, 0, sgNone, "This cell is partially on fire.")
|
||||
WALL( '#', 0xA07070, "dead wall", waDeadwall, WF_WALL | WF_HIGHWALL | WF_ON, RESERVED, 0, sgCave, deadcavehelp)
|
||||
WALL( '.', 0x401010, "dead floor", waDeadfloor, ZERO | WF_ON, RESERVED, 0, sgNone,deadcavehelp)
|
||||
WALL( '.', 0x905050, "rubble", waDeadfloor2, ZERO | WF_ON, RESERVED, 1, sgNone, "Dead floor, with some rubble.")
|
||||
WALL( '#', 0xD0D010, "weird rock", waWaxWall, WF_WALL | WF_HIGHWALL, RESERVED, 0, sgNone,
|
||||
"A weirdly colored rock. Hyperentomologists claim that the "
|
||||
"Hyperbug armies use these rocks to navigate back home after a victorious battle."
|
||||
|
@ -932,7 +932,7 @@ WALL( '#', 0x8080C0, "crystal cabinet", waGlass, WF_WALL, RESERVED, 0, sgNone,
|
|||
"using an Orb of Aether, your Aether power will be completely drained."
|
||||
)
|
||||
WALL( '#', 0xC0C0C0, "wall of Camelot", waCamelot, WF_WALL | WF_HIGHWALL, RESERVED, 0, sgNone, camelothelp )
|
||||
WALL( '+', 0xA06000, "Round Table", waRoundTable, WF_WALL | WF_NONBLOCK, RESERVED, 1, sgNone, camelothelp )
|
||||
WALL( '+', 0xA06000, "Round Table", waRoundTable, WF_WALL | WF_NONBLOCK | WF_ON, RESERVED, 1, sgNone, camelothelp )
|
||||
WALL( '=', 0x0000A0, "moat of Camelot", waCamelotMoat, WF_WATER, RESERVED, 0, sgWater, camelothelp)
|
||||
WALL( '+', 0x606060, "big statue of Cthulhu", waBigStatue, WF_WALL, RESERVED, 0, sgNone,
|
||||
"These statues of Cthulhu are too large to carry, and they don't look too "
|
||||
|
@ -941,24 +941,24 @@ WALL( '+', 0x606060, "big statue of Cthulhu", waBigStatue, WF_WALL, RESERVED, 0,
|
|||
"a statue, you push the statue to the cell you left.\n"
|
||||
)
|
||||
WALL( '=', 0x0000A0, "sea", waSea, WF_WATER, RESERVED, 0, sgWater, caribbeanhelp)
|
||||
WALL( '+', 0x0000A0, "boat", waBoat, ZERO | WF_BOAT | WF_NOFLIGHT, RESERVED, 0, sgNone,
|
||||
WALL( '+', 0x0000A0, "boat", waBoat, ZERO | WF_BOAT | WF_NOFLIGHT | WF_ON, RESERVED, 0, sgNone,
|
||||
"Hyperbolic pirates do not need huge ships, since so many lands to conquest "
|
||||
"are so close. These small boats are enough for them.\n\n"
|
||||
"Boats allow you to go through water. If you are in a boat, you can move into "
|
||||
"a water cell (and the boat will come with you)."
|
||||
)
|
||||
WALL( '.', 0x00FF00, "island", waCIsland, ZERO | WF_CISLAND, RESERVED, 0, sgNone, cislandhelp)
|
||||
WALL( '.', 0x80C060, "island", waCIsland2, ZERO | WF_CISLAND, RESERVED, 0, sgNone, cislandhelp)
|
||||
WALL( '.', 0x00FF00, "island", waCIsland, ZERO | WF_CISLAND | WF_ON, RESERVED, 0, sgNone, cislandhelp)
|
||||
WALL( '.', 0x80C060, "island", waCIsland2, ZERO | WF_CISLAND | WF_ON, RESERVED, 0, sgNone, cislandhelp)
|
||||
WALL( '#', 0x006000, "tree", waCTree, WF_WALL | WF_HIGHWALL | WF_CONE | WF_CISLAND, RESERVED, 0, sgTree,
|
||||
"The forests of Caribbean are too dense to be traversed by humans, "
|
||||
"and they are hard to burn. Many colorful parrots can be found there."
|
||||
)
|
||||
WALL( ',', 0x800000, "rock I", waRed1, ZERO | WF_RED, RESERVED, 1, sgNone, redrockhelp)
|
||||
WALL( ':', 0xC00000, "rock II", waRed2, ZERO | WF_RED, RESERVED, 2, sgNone, redrockhelp)
|
||||
WALL( ';', 0xFF0000, "rock III", waRed3, ZERO | WF_RED, RESERVED, 3, sgNone, redrockhelp)
|
||||
WALL( ',', 0x800000, "rock I", waRed1, ZERO | WF_RED | WF_ON, RESERVED, 1, sgNone, redrockhelp)
|
||||
WALL( ':', 0xC00000, "rock II", waRed2, ZERO | WF_RED | WF_ON, RESERVED, 2, sgNone, redrockhelp)
|
||||
WALL( ';', 0xFF0000, "rock III", waRed3, ZERO | WF_RED | WF_ON, RESERVED, 3, sgNone, redrockhelp)
|
||||
WALL( '.', 0xD0D0D0, "minefield", waMineUnknown, ZERO, RESERVED, 0, sgNone, minedesc)
|
||||
WALL( '.', 0xD0D0D0, "minefield", waMineMine, ZERO, RESERVED, 0, sgNone, minedesc)
|
||||
WALL( '.', 0x909090, "cell without mine", waMineOpen, ZERO, RESERVED, 0, sgNone, minedesc)
|
||||
WALL( '.', 0x909090, "cell without mine", waMineOpen, ZERO | WF_ON, RESERVED, 0, sgNone, minedesc)
|
||||
WALL( '+', 0x808000, "stranded boat", waStrandedBoat, ZERO | WF_BOAT | WF_NOFLIGHT, RESERVED, 0, sgNone,
|
||||
"This boat cannot go through the sand. But if you sit inside and "
|
||||
"wait for the tide, you will be able to use it to travel through the Ocean."
|
||||
|
@ -966,17 +966,17 @@ WALL( '+', 0x808000, "stranded boat", waStrandedBoat, ZERO | WF_BOAT | WF_NOFLIG
|
|||
WALL( '#', 0xFFD500, "palace wall", waPalace, WF_WALL | WF_HIGHWALL, RESERVED, 0, sgNone, palacedesc )
|
||||
WALL( '+', 0xFFFFFF, "closed gate", waClosedGate, WF_WALL | WF_HIGHWALL, RESERVED, 0, sgNone, gatedesc )
|
||||
WALL( '-', 0x404040, "open gate", waOpenGate, ZERO, RESERVED, 0, sgNone, gatedesc )
|
||||
WALL( '_', 0xC00000, "closing plate", waClosePlate, ZERO, RESERVED, 0, sgNone, gatedesc )
|
||||
WALL( '_', 0x00C050, "opening plate", waOpenPlate, ZERO, RESERVED, 0, sgNone, gatedesc )
|
||||
WALL( '_', 0x202020, "trapdoor", waTrapdoor, ZERO, RESERVED, 0, sgNone, "This floor will fall after someone goes there. Go quickly!" )
|
||||
WALL( '+', 0xFF0000, "giant rug", waGiantRug, ZERO, RESERVED, 0, sgNone,
|
||||
WALL( '_', 0xC00000, "closing plate", waClosePlate, ZERO | WF_ON, RESERVED, 0, sgNone, gatedesc )
|
||||
WALL( '_', 0x00C050, "opening plate", waOpenPlate, ZERO | WF_ON, RESERVED, 0, sgNone, gatedesc )
|
||||
WALL( '_', 0x202020, "trapdoor", waTrapdoor, ZERO | WF_ON, RESERVED, 0, sgNone, "This floor will fall after someone goes there. Go quickly!" )
|
||||
WALL( '+', 0xFF0000, "giant rug", waGiantRug, ZERO | WF_ON, RESERVED, 0, sgNone,
|
||||
"This is the biggest Hypersian Rug you have ever seen! "
|
||||
"Unfortunately, it is too large to take it as a trophy." )
|
||||
WALL( '#', 0xfffff0, "platform", waPlatform, WF_WALL | WF_HIGHWALL, RESERVED, 0, sgNone, "You can stand here.")
|
||||
WALL( '#', 0x909090, "stone gargoyle", waGargoyle, WF_WALL | WF_HIGHWALL, RESERVED, 0, sgNone, gargdesc)
|
||||
WALL( '.', 0xB0B0B0, "stone gargoyle floor", waGargoyleFloor, ZERO, RESERVED, 1, sgNone, gargdesc)
|
||||
WALL( '.', 0x909090, "rubble", waRubble, ZERO, RESERVED, 1, sgNone, "Some rubble.")
|
||||
WALL( '+', 0x804000, "ladder", waLadder, ZERO, RESERVED, 0, sgNone,
|
||||
WALL( '#', 0x909090, "stone gargoyle", waGargoyle, WF_WALL | WF_HIGHWALL | WF_NONBLOCK, RESERVED, 0, sgNone, gargdesc)
|
||||
WALL( '.', 0xB0B0B0, "stone gargoyle floor", waGargoyleFloor, ZERO | WF_ON, RESERVED, 1, sgNone, gargdesc)
|
||||
WALL( '.', 0x909090, "rubble", waRubble, ZERO | WF_ON, RESERVED, 1, sgNone, "Some rubble.")
|
||||
WALL( '+', 0x804000, "ladder", waLadder, ZERO | WF_ON, RESERVED, 0, sgNone,
|
||||
"You can use this ladder to climb the Tower."
|
||||
)
|
||||
WALL( '#', 0xC0C0C0, "limestone wall", waStone, WF_WALL | WF_HIGHWALL, RESERVED, 0, sgNone, "Simply a wall. Mostly.")
|
||||
|
@ -985,13 +985,13 @@ WALL( '^', 0x804000, "Bonfire", waBonfireOff, WF_WALL | WF_ACTIVABLE, RESERVED,
|
|||
)
|
||||
WALL( '^', 0x8D694F, "Thumper", waThumperOn, WF_WALL | WF_TIMEOUT | WF_PUSHABLE | WF_THUMPER, RESERVED, 0, sgNone,
|
||||
"A device that attracts sandworms and other enemies. You need to activate it.")
|
||||
WALL( '^', 0x804000, "Eternal Fire", waEternalFire, WF_FIRE, RESERVED, 0, sgNone,
|
||||
WALL( '^', 0x804000, "Eternal Fire", waEternalFire, WF_FIRE | WF_ON, RESERVED, 0, sgNone,
|
||||
"This fire never burns out."
|
||||
)
|
||||
WALL( '.', 0x909090, "stone gargoyle bridge", waGargoyleBridge, ZERO, RESERVED, 1, sgNone, gargdesc)
|
||||
WALL( '.', 0x909090, "stone gargoyle bridge", waGargoyleBridge, ZERO | WF_ON, RESERVED, 1, sgNone, gargdesc)
|
||||
WALL( '#', 0x309060, "temporary wall", waTempWall, WF_WALL | WF_HIGHWALL | WF_TIMEOUT, RESERVED, 0, sgNone, twdesc)
|
||||
WALL( '.', 0x309060, "temporary floor", waTempFloor, ZERO | WF_TIMEOUT, RESERVED, 1, sgNone, twdesc)
|
||||
WALL( '.', 0x309060, "temporary bridge", waTempBridge, ZERO | WF_TIMEOUT, RESERVED, 1, sgNone, twdesc)
|
||||
WALL( '.', 0x309060, "temporary floor", waTempFloor, ZERO | WF_TIMEOUT | WF_ON, RESERVED, 1, sgNone, twdesc)
|
||||
WALL( '.', 0x309060, "temporary bridge", waTempBridge, ZERO | WF_TIMEOUT | WF_ON, RESERVED, 1, sgNone, twdesc)
|
||||
WALL( '#', 0x3030FF, "charged wall", waCharged, WF_WALL | WF_HIGHWALL, RESERVED, 0, sgNone, elecdesc)
|
||||
WALL( '#', 0xFF3030, "grounded wall", waGrounded, WF_WALL | WF_HIGHWALL, RESERVED, 0, sgNone, elecdesc)
|
||||
WALL( '#', 0xA0A060, "sandstone wall", waSandstone, WF_WALL | WF_HIGHWALL, RESERVED, 0, sgNone, elecdesc)
|
||||
|
@ -1009,8 +1009,8 @@ WALL( '#', 0x764e7c, "rosebush", waRose, WF_WALL | WF_HIGHWALL | WF_THORNY, RESE
|
|||
WALL( '#', 0xC0C000, "warp gate", waWarpGate, WF_WALL | WF_HIGHWALL, RESERVED, 0, sgNone,
|
||||
"This gate separates the warped area from the normal land.")
|
||||
WALL( '+', 0x804000, "trunk", waTrunk, ZERO | WF_NOFLIGHT, RESERVED, 0, sgNone, "The skeleton of a tree.")
|
||||
WALL( '-', 0x402000, "solid branch", waSolidBranch, ZERO, RESERVED, 0, sgNone, "Branches here could bear your weight easily.")
|
||||
WALL( ':', 0x804000, "weak branch", waWeakBranch, ZERO, RESERVED, 0, sgNone,
|
||||
WALL( '-', 0x402000, "solid branch", waSolidBranch, ZERO | WF_ON, RESERVED, 0, sgNone, "Branches here could bear your weight easily.")
|
||||
WALL( ':', 0x804000, "weak branch", waWeakBranch, ZERO | WF_ON, RESERVED, 0, sgNone,
|
||||
"Branches here will bear you weight, but if you use them to move (not fall) to an unstable place, they will break.")
|
||||
WALL( '+', 0x60C060, "canopy", waCanopy, ZERO, RESERVED, 0, sgNone,
|
||||
"Only thin twigs and leaves here. They may bear fruits, but for you, these cells count "
|
||||
|
@ -1018,33 +1018,33 @@ WALL( '+', 0x60C060, "canopy", waCanopy, ZERO, RESERVED, 0, sgNone,
|
|||
)
|
||||
WALL( '#', 0xD0C060, "barrow wall", waBarrowWall, WF_WALL | WF_HIGHWALL, RESERVED, 0, sgNone, "This wall is quite strong. You will need another way in.")
|
||||
WALL( '#', 0x90A060, "barrow", waBarrowDig, WF_WALL | WF_HIGHWALL, RESERVED, 0, sgNone, "Your Orb of the Sword can be used to dig here.")
|
||||
WALL( '#', 0xE0E0E0, "stone statue", waPetrified, WF_WALL | WF_HIGHWALL, RESERVED, 0, sgNone, "A petrified creature.")
|
||||
WALL( '#', 0xE0E0E0, "stone statue", waPetrified, WF_WALL | WF_HIGHWALL | WF_NONBLOCK, RESERVED, 0, sgNone, "A petrified creature.")
|
||||
WALL( '.', 0xE8E8E8, "tower of Camelot", waTower, ZERO, RESERVED, 3, sgNone, camelothelp)
|
||||
WALL( '-', 0x402000, "big bush", waBigBush, ZERO | WF_NOFLIGHT, RESERVED, 0, sgNone,
|
||||
WALL( '-', 0x402000, "big bush", waBigBush, ZERO | WF_NOFLIGHT | WF_ON, RESERVED, 0, sgNone,
|
||||
"You can hold this bush to climb the Lost Mountain. "
|
||||
"Bushes block the movement of birds."
|
||||
)
|
||||
WALL( ':', 0x804000, "small bush", waSmallBush, ZERO | WF_NOFLIGHT, RESERVED, 0, sgNone,
|
||||
WALL( ':', 0x804000, "small bush", waSmallBush, ZERO | WF_NOFLIGHT | WF_ON, RESERVED, 0, sgNone,
|
||||
"You can hold this bush to climb the Lost Mountain, "
|
||||
"but it is not very strong -- it will get destroyed "
|
||||
"if you climb from it into an unstable location. "
|
||||
"Bushes block the movement of birds.")
|
||||
WALL( '.', 0xFFFF00, "Reptile floor", waReptile, ZERO | WF_REPTILE, RESERVED, 0, sgNone, reptiledesc)
|
||||
WALL( '.', 0xFFFF00, "Reptile bridge", waReptileBridge, ZERO | WF_REPTILE, RESERVED, 0, sgNone, reptiledesc)
|
||||
WALL( '.', 0xFFFF00, "invisible floor", waInvisibleFloor, ZERO, RESERVED, 0, sgNone, NODESCYET)
|
||||
WALL( '.', 0xFFFF00, "Reptile floor", waReptile, ZERO | WF_REPTILE | WF_ON, RESERVED, 0, sgNone, reptiledesc)
|
||||
WALL( '.', 0xFFFF00, "Reptile bridge", waReptileBridge, ZERO | WF_REPTILE | WF_ON, RESERVED, 0, sgNone, reptiledesc)
|
||||
WALL( '.', 0xFFFF00, "invisible floor", waInvisibleFloor, ZERO | WF_ON, RESERVED, 0, sgNone, NODESCYET)
|
||||
WALL( '#', 0xC0C0FF, "mirror wall", waMirrorWall, WF_WALL, RESERVED, 0, sgNone, mirroreddesc)
|
||||
WALL( '.', 0xE0E0E0, "stepping stones", waPetrifiedBridge, ZERO, RESERVED, 1, sgNone, "A petrified creature.")
|
||||
WALL( '.', 0xE0E0E0, "stepping stones", waPetrifiedBridge, WF_ON, RESERVED, 1, sgNone, "A petrified creature.")
|
||||
WALL( '#', 0x309060, "temporary wall", waTempBridgeBlocked, WF_WALL | WF_HIGHWALL | WF_TIMEOUT, RESERVED, 0, sgNone, twdesc)
|
||||
WALL( 'S', 0xB0B0B0, "warrior statue", waTerraWarrior, WF_WALL, RESERVED, 0, sgNone, terradesc)
|
||||
WALL( '=', 0xB0B0B0, "bubbling slime", waBubble, ZERO | WF_CHASM, RESERVED, 0, sgNone, NODESC)
|
||||
WALL( '^', 0xD00000, "arrow trap", waArrowTrap, ZERO, RESERVED, 0, sgNone, arrowtrapdesc)
|
||||
WALL( '^', 0xD00000, "arrow trap", waArrowTrap, WF_ON, RESERVED, 0, sgNone, arrowtrapdesc)
|
||||
WALL( '=', 0xE2E2E2, "mercury river", waMercury, ZERO | WF_CHASM, RESERVED, 0, sgNone, "A river of mercury.")
|
||||
WALL( '&', 0xD00000, "lava", waMagma, ZERO, RESERVED, 1, sgNone, lavadesc)
|
||||
WALL( '=', 0x804000, "dock", waDock, ZERO, RESERVED, 0, sgNone, "A dock.")
|
||||
WALL( '^', 0xFF8000, "burning dock", waBurningDock, WF_FIRE | WF_TIMEOUT, RESERVED, 0, sgNone, "A burning dock.")
|
||||
WALL( '=', 0x804000, "dock", waDock, ZERO | WF_ON, RESERVED, 0, sgNone, "A dock.")
|
||||
WALL( '^', 0xFF8000, "burning dock", waBurningDock, WF_FIRE | WF_TIMEOUT | WF_ON, RESERVED, 0, sgNone, "A burning dock.")
|
||||
WALL( '#', 0xE04030, "ruin wall", waRuinWall, WF_WALL | WF_HIGHWALL, RESERVED, 0, sgNone, ruindesc)
|
||||
WALL( '#', 0xA04060, "Brownian generator", waBrownian, WF_WALL | WF_HIGHWALL, RESERVED, 0, sgNone, NODESC)
|
||||
WALL( '^', 0xC05000, "fire trap", waFireTrap, ZERO, RESERVED, 0, sgNone,
|
||||
WALL( '^', 0xC05000, "fire trap", waFireTrap, ZERO | WF_ON, RESERVED, 0, sgNone,
|
||||
"This trap will explode when stepped on, setting all the adjacent cells on fire. However, this happens on the next turn, "
|
||||
"so you can safely escape if you are fast enough.")
|
||||
WALL( '^', 0xFD692F, "Explosive Barrel", waExplosiveBarrel, WF_WALL | WF_PUSHABLE, RESERVED, 0, sgNone,
|
||||
|
@ -1285,7 +1285,12 @@ LAND( 0x4040C0, "Sea Border", laOceanWall, ZERO | LF_TECHNICAL | LF_SEA, itNone,
|
|||
|
||||
LAND( 0x4040C0, "Elemental Planes", laElementalWall, ZERO | LF_ELEMENTAL, itElemental, RESERVED, elemdesc)
|
||||
NATIVE((m == moAirElemental || m == moEarthElemental || m == moWaterElemental || m == moFireElemental) ? 1 : 0)
|
||||
REQ(KILL(moAirElemental, laWhirlwind) KILL(moWaterElemental, laLivefjord) KILL(moEarthElemental, laDeadCaves) KILL(moFireElemental, laDragon))
|
||||
REQ(
|
||||
IFINGAME(laWhirlwind, KILL(moAirElemental, laWhirlwind), ITEMS(itDiamond, U10))
|
||||
IFINGAME(laLivefjord, KILL(moWaterElemental, laLivefjord), ITEMS(itElixir, U10))
|
||||
IFINGAME(laDeadCaves, KILL(moEarthElemental, laDeadCaves), ITEMS(itGold, U10))
|
||||
IFINGAME(laDragon, KILL(moFireElemental, laDragon), ITEMS(itSpice, U10))
|
||||
)
|
||||
|
||||
LAND( 0xE08020, "Canvas", laCanvas, ZERO | LF_TECHNICAL, itNone, RESERVED, "A fake Land with colored floors.")
|
||||
NATIVE(0)
|
||||
|
@ -1293,11 +1298,11 @@ LAND( 0xE08020, "Canvas", laCanvas, ZERO | LF_TECHNICAL, itNone, RESERVED, "A fa
|
|||
|
||||
LAND( 0x00C000, "Palace Quest", laPrincessQuest, ZERO, itSavedPrincess, RESERVED, princessdesc) // fake
|
||||
NATIVE(isNative(laPalace, m))
|
||||
REQ(ACCONLY(laPalace) KILL(moVizier, laPalace))
|
||||
REQ(ACCONLY(laPalace) INMODE(princess::challenge) KILL(moVizier, laPalace))
|
||||
|
||||
LAND( 0xD0D060, "Wild West", laWildWest, ZERO, itBounty, RESERVED, wildwestdesc)
|
||||
NATIVE((m == moOutlaw) ? 2 : 0)
|
||||
REQ( NEVER )
|
||||
REQ( ALWAYS )
|
||||
|
||||
LAND( 0x80A080, "Land of Storms", laStorms, ZERO | LF_TROLL | LF_ELECTRIC, itFulgurite, RESERVED, elecdesc)
|
||||
NATIVE((m == moMetalBeast || m == moMetalBeast2 || m == moStormTroll) ? 1 : 0)
|
||||
|
@ -1388,7 +1393,14 @@ LAND( 0x90A548, "Trollheim", laTrollheim, ZERO, itTrollEgg, RESERVED,
|
|||
"these Trolls yourself?"
|
||||
)
|
||||
NATIVE(isTroll(m) ? 1 : 0)
|
||||
REQ( KILL(moTroll, laCaves) KILL(moDarkTroll, laDeadCaves) KILL(moRedTroll, laRedRock) KILL(moStormTroll, laStorms) KILL(moForestTroll, laOvergrown) KILL(moFjordTroll, laLivefjord) )
|
||||
REQ(
|
||||
IFINGAME(laCaves, KILL(moTroll, laCaves), ITEMS(itSpice, 10))
|
||||
IFINGAME(laDeadCaves, KILL(moDarkTroll, laDeadCaves), ITEMS(itGold, 10))
|
||||
IFINGAME(laRedRock, KILL(moRedTroll, laRedRock), ITEMS(itSpice, 10))
|
||||
IFINGAME(laStorms, KILL(moStormTroll, laStorms), ITEMS(itElixir, 10))
|
||||
IFINGAME(laOvergrown, KILL(moForestTroll, laOvergrown), ITEMS(itRuby, 10))
|
||||
IFINGAME(laLivefjord, KILL(moFjordTroll, laLivefjord), ITEMS(itGold, 10))
|
||||
)
|
||||
|
||||
LAND( 0xFF7518, "Halloween", laHalloween, ZERO, itTreat, RESERVED, halloweendesc)
|
||||
NATIVE((m == moGhost || m == moZombie || m == moWitch ||
|
||||
|
@ -1400,13 +1412,16 @@ LAND( 0xFF7518, "Halloween", laHalloween, ZERO, itTreat, RESERVED, halloweendesc
|
|||
m == moLancer || m == moFireFairy ||
|
||||
m == moBomberbird || m == moRatlingAvenger ||
|
||||
m == moVineBeast || m == moDragonHead || m == moDragonTail) ? 1 : 0)
|
||||
REQ( NEVER )
|
||||
REQ( ALWAYS )
|
||||
|
||||
LAND( 0x605040, "Dungeon", laDungeon, ZERO | LF_GRAVITY | LF_EQUI, itSlime, RESERVED,
|
||||
"The result of a collaboration of the Great Vizier and the Wizard of the Ivory Tower."
|
||||
)
|
||||
NATIVE(m == moBat ? 2 : m == moSkeleton || m == moGhost ? 1 : 0)
|
||||
REQ(ITEMS(itPalace, U5) ITEMS(itIvory, U5))
|
||||
REQ(
|
||||
IFINGAME(laPalace, ITEMS(itPalace, U5), ITEMS(itDiamond, U10))
|
||||
IFINGAME(laIvoryTower, ITEMS(itIvory, U5), ITEMS(itElixir, U10))
|
||||
)
|
||||
|
||||
LAND( 0x603000, "Lost Mountain", laMountain, ZERO | LF_GRAVITY | LF_CYCLIC, itAmethyst, RESERVED,
|
||||
"Gravitational anomalies in the Jungle create mountains "
|
||||
|
@ -1415,7 +1430,11 @@ LAND( 0x603000, "Lost Mountain", laMountain, ZERO | LF_GRAVITY | LF_CYCLIC, itAm
|
|||
"Cells adjacent to Ivies count as stable (but Ivies "
|
||||
"cannot climb themselves or other Ivies).")
|
||||
NATIVE(m == moEagle || m == moMonkey || isIvy(m) || m == moFriendlyIvy ? 1 : 0)
|
||||
REQ(ITEMS(itRuby, U5) ITEMS(itIvory, U5) ACCONLY(laJungle))
|
||||
REQ(
|
||||
ITEMS(itRuby, U5)
|
||||
IFINGAME(laIvoryTower, ITEMS(itIvory, U5), ITEMS(itElixir, U10))
|
||||
ACCONLY(laJungle)
|
||||
)
|
||||
|
||||
LAND( 0xFFFF00, "Reptiles", laReptile, ZERO, itDodeca, RESERVED, reptiledesc)
|
||||
NATIVE(m == moReptile ? 1 : 0)
|
||||
|
@ -1435,7 +1454,7 @@ LAND( 0xC000C0, "Crossroads V", laCrossroads5, ZERO, itHyperstone, RESERVED, "Ex
|
|||
|
||||
LAND( 0xC0C0C0, "Cellular Automaton", laCA, ZERO | LF_TECHNICAL, itNone, RESERVED, cadesc)
|
||||
NATIVE(0)
|
||||
REQ(NEVER)
|
||||
REQ(ALWAYS)
|
||||
|
||||
LAND( 0xC0C0FF, "Mirror Wall", laMirrorWall, ZERO | LF_TECHNICAL | LF_INMIRRORORWALL, itShard, RESERVED, mirroreddesc)
|
||||
NATIVE(isNative(laMirror, m))
|
||||
|
@ -1463,7 +1482,7 @@ LAND( 0xA06000, "Volcanic Wasteland", laVolcano, ZERO, itLavaLily, RESERVED, lav
|
|||
|
||||
LAND( 0x8080FF, "Blizzard", laBlizzard, ZERO | LF_ICY, itBlizzard, RESERVED, blizzarddesc)
|
||||
NATIVE((m == moVoidBeast || m == moIceGolem) ? 2 : 0)
|
||||
REQ(ITEMS(itDiamond, U5) ITEMS(itWindstone, U5))
|
||||
REQ(IFINGAME(laWhirlwind, ITEMS(itDiamond, U5) ITEMS(itWindstone, U5), ITEMS(itDiamond, 10) GOLD(R60)))
|
||||
|
||||
LAND( 0x207068, "Hunting Ground", laHunting, ZERO, itHunting, RESERVED, huntingdesc)
|
||||
NATIVE(m == moHunterDog ? 1 : 0)
|
||||
|
@ -1491,7 +1510,9 @@ LAND( 0x80FF00, "Docks", laDocks, ZERO | LF_SEA, itDock, RESERVED, NODESCYET)
|
|||
|
||||
LAND( 0x306030, "Ruined City", laRuins, ZERO, itRuins, RESERVED, ruindesc)
|
||||
NATIVE(among(m, moPair, moHexDemon, moAltDemon, moMonk, moCrusher) ? 2 : m == moSkeleton ? 1 : 0)
|
||||
REQ(KILL(moSkeleton, laPalace))
|
||||
REQ(
|
||||
IFINGAME(laPalace, KILL(moSkeleton, laPalace), ITEMS(itRuby, U10))
|
||||
)
|
||||
|
||||
LAND( 0x306030, "Magnetosphere", laMagnetic, ZERO, itMagnet, RESERVED, NODESCYET)
|
||||
NATIVE(isMagneticPole(m) ? 2 : 0)
|
||||
|
@ -1548,9 +1569,9 @@ LAND( 0x30FF30, "Irradiated Field", laVariant, ZERO, itVarTreasure, RESERVED,
|
|||
|
||||
LAND( 0x202020, "Space Rocks", laAsteroids, ZERO, itAsteroid, RESERVED, rock_description)
|
||||
ITEM( '!', 0xFFD0D0, "Fuel", itAsteroid, IC_TREASURE, ZERO, RESERVED, osNone, rock_description)
|
||||
MONSTER('A', 0x606040, "Space Rock", moAsteroid, ZERO, RESERVED, moAsteroid, rock_description)
|
||||
MONSTER('A', 0x606040, "Space Rock", moAsteroid, ZERO, RESERVED, moYeti, rock_description)
|
||||
NATIVE(m == moAsteroid ? 2 : 0)
|
||||
REQ( NEVER )
|
||||
REQ( ALWAYS )
|
||||
|
||||
LAND( 0x00C0C0, "Wetland", laWet, ZERO, itWet, RESERVED,
|
||||
"Some people have definitely drowned in this treacherous area. Better be careful!"
|
||||
|
@ -1638,7 +1659,7 @@ WALL( '$', 0xFD692F, "Crate", waCrateCrate, WF_WALL | WF_PUSHABLE, RESERVED, 0,
|
|||
"These crates can be pushed."
|
||||
)
|
||||
|
||||
WALL( '.', 0x40FD40, "Target", waCrateTarget, 0, RESERVED, 0, sgNone,
|
||||
WALL( '.', 0x40FD40, "Target", waCrateTarget, 0 | WF_ON, RESERVED, 0, sgNone,
|
||||
"Push all your crates on targets."
|
||||
)
|
||||
|
||||
|
@ -1776,3 +1797,5 @@ MONSTER( '*', 0, "vertex", moRogueviz, ZERO | CF_TECHNICAL, RESERVED, moN
|
|||
#undef ACCONLY2
|
||||
#undef ACCONLY3
|
||||
#undef ACCONLYF
|
||||
#undef IFINGAME
|
||||
#undef INMODE
|
||||
|
|
|
@ -376,6 +376,7 @@ EX void full_ystrafe_camera(ld t) {
|
|||
EX ld third_person_rotation = 0;
|
||||
|
||||
EX void full_rotate_camera(int dir, ld val) {
|
||||
if(!val) return;
|
||||
if(rug::rug_control() && lshiftclick) {
|
||||
val *= camera_rot_speed;
|
||||
hyperpoint h;
|
||||
|
@ -524,7 +525,7 @@ EX void handleKeyNormal(int sym, int uni) {
|
|||
|
||||
if(!(uni >= 'A' && uni <= 'Z') && DEFAULTCONTROL && !game_keys_scroll) {
|
||||
for(int i=0; i<8; i++)
|
||||
if(among(sym, keys_vi[i], keys_wasd[i], keys_numpad[i]))
|
||||
if(among(sym, keys_vi[i], keys_wasd[i], (uni >= '0' && uni <= '9' && !ISMAC) ? -1 : keys_numpad[i]))
|
||||
movepckeydir(i);
|
||||
}
|
||||
|
||||
|
@ -872,7 +873,7 @@ EX void mainloopiter() {
|
|||
targetclick = pandora_leftclick | pandora_rightclick;
|
||||
pandora_leftclick = pandora_rightclick = 0;
|
||||
#else
|
||||
targetclick = keystate[SDLK_RSHIFT] | keystate[SDLK_LSHIFT];
|
||||
targetclick = keystate[SDL12(SDLK_RSHIFT, SDL_SCANCODE_RSHIFT)] | keystate[SDL12(SDLK_LSHIFT, SDL_SCANCODE_LSHIFT)];
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
|
@ -957,7 +958,7 @@ EX void mainloopiter() {
|
|||
}
|
||||
else sc_ticks = ticks;
|
||||
|
||||
if(game_keys_scroll && !shmup::on && (cmode & sm::NORMAL) && !keystate[SDLK_LALT] && !keystate[SDLK_RALT]) {
|
||||
if(game_keys_scroll && !shmup::on && (cmode & sm::NORMAL) && !keystate[SDL12(SDLK_LALT, SDL_SCANCODE_LALT)] && !keystate[SDL12(SDLK_RALT, SDL_SCANCODE_RALT)]) {
|
||||
rug::using_rugview urv;
|
||||
auto& lastticks = sc_ticks2;
|
||||
ld t = (ticks - lastticks) * shiftmul / 1000.;
|
||||
|
|
12
crossbow.cpp
12
crossbow.cpp
|
@ -28,6 +28,7 @@ EX namespace bow {
|
|||
#if HDR
|
||||
enum eWeapon { wBlade, wCrossbow };
|
||||
enum eCrossbowStyle { cbBull, cbGeodesic, cbGeometric };
|
||||
const string bowName[] = { "bull", "geod", "geom" };
|
||||
#endif
|
||||
|
||||
EX eWeapon weapon;
|
||||
|
@ -301,7 +302,7 @@ EX void add_fire(cell *c) {
|
|||
return;
|
||||
}
|
||||
clear_bowpath();
|
||||
checked_move_issue = miVALID;
|
||||
checked_move_issue.type = miVALID;
|
||||
pcmove pcm;
|
||||
pcm.checkonly = false;
|
||||
changes.init(false);
|
||||
|
@ -358,7 +359,7 @@ EX bool fire_on_mouse(cell *c) {
|
|||
return false;
|
||||
}
|
||||
gen_bowpath_map();
|
||||
checked_move_issue = miVALID;
|
||||
checked_move_issue.type = miVALID;
|
||||
pcmove pcm;
|
||||
pcm.checkonly = false;
|
||||
changes.init(false);
|
||||
|
@ -369,6 +370,8 @@ EX bool fire_on_mouse(cell *c) {
|
|||
return b;
|
||||
}
|
||||
|
||||
EX int rusalka_curses = 0;
|
||||
|
||||
EX void shoot() {
|
||||
flagtype attackflags = AF_BOW;
|
||||
if(items[itOrbSpeed]&1) attackflags |= AF_FAST;
|
||||
|
@ -382,6 +385,7 @@ EX void shoot() {
|
|||
vector<pair<cell*, int>> healthy_dragons;
|
||||
map<cell*, pair<int, int>> kraken_hits;
|
||||
int dragon_hits = 0;
|
||||
rusalka_curses = 0;
|
||||
|
||||
// for achievements
|
||||
for(auto& mov: bowpath) {
|
||||
|
@ -458,6 +462,8 @@ EX void shoot() {
|
|||
|
||||
if(m && attackMonster(c, attackflags | AF_MSG, who)) hit_anything = true;
|
||||
|
||||
if(m == moRusalka) rusalka_curses++;
|
||||
|
||||
if(!c->monst || isAnyIvy(m)) {
|
||||
spread_plague(cf, c, movei(mov.prev).rev().d, moPlayer);
|
||||
produceGhost(c, m, moPlayer);
|
||||
|
@ -514,7 +520,7 @@ EX bool have_bow_target() {
|
|||
int res = create_path();
|
||||
if(res == -1) continue;
|
||||
|
||||
checked_move_issue = miVALID;
|
||||
checked_move_issue.type = miVALID;
|
||||
pcmove pcm;
|
||||
pcm.checkonly = true;
|
||||
changes.init(true);
|
||||
|
|
|
@ -660,6 +660,9 @@ int read_cheat_args() {
|
|||
PHASEFROM(2);
|
||||
shift(); vid.stereo_mode = eStereo(argi());
|
||||
}
|
||||
else if(argis("-save-cheats")) {
|
||||
save_cheats = true;
|
||||
}
|
||||
else if(argis("-cmove")) {
|
||||
PHASE(3); shift();
|
||||
for(char c: args()) cheat_move(c);
|
||||
|
|
|
@ -1975,7 +1975,7 @@ void dqi_poly::draw() {
|
|||
if(isize(glcoords) <= 1) return;
|
||||
|
||||
cyl::loop_min = cyl::loop_max = 0;
|
||||
if(sphere && mdBandAny())
|
||||
if((sphere && mdBandAny()) || pmodel == mdPolar)
|
||||
cyl::adjust(tinf);
|
||||
|
||||
int poly_limit = max(vid.xres, vid.yres) * 2;
|
||||
|
|
|
@ -368,7 +368,7 @@ EX void bfs() {
|
|||
c2->wall = waSea;
|
||||
|
||||
if(c2 && signed(c2->cpdist) > d+1) {
|
||||
if(WDIM == 3 && !gmatrix.count(c2)) {
|
||||
if(WDIM == 3 && (d > 2 && !gmatrix.count(c2))) {
|
||||
if(!first7) first7 = qb;
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -409,7 +409,8 @@ EX bool sizes_known() {
|
|||
if(aperiodic) return false;
|
||||
if(currentmap->strict_tree_rules()) return true;
|
||||
if(arb::in()) return false;
|
||||
return true;
|
||||
if(INVERSE) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
EX bool trees_known() {
|
||||
|
@ -654,7 +655,7 @@ void celldrawer::do_viewdist() {
|
|||
if(!dist_label_colored) dc = dist_label_color;
|
||||
|
||||
if(label != "")
|
||||
queuestr(V, (isize(label) > 1 ? .6 : 1), label, 0xFF000000 + dc, 1);
|
||||
queuestr(V, (isize(label) > 1 ? .6 : 1) * mapfontscale / 100, label, 0xFF000000 + dc, 1);
|
||||
}
|
||||
|
||||
EX void viewdist_configure_dialog() {
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
#include <string>
|
||||
|
||||
namespace hr {
|
||||
string scorefile = "fakemobile_score.txt";
|
||||
std::string scorefile = "fakemobile_score.txt";
|
||||
}
|
||||
|
||||
#include <SDL/SDL.h>
|
||||
|
|
1
fake.cpp
1
fake.cpp
|
@ -75,6 +75,7 @@ EX namespace fake {
|
|||
}
|
||||
|
||||
hrmap_fake() {
|
||||
underlying_map = nullptr;
|
||||
in_underlying([this] { initcells(); underlying_map = currentmap; });
|
||||
for(hrmap*& m: allmaps) if(m == underlying_map) m = NULL;
|
||||
}
|
||||
|
|
|
@ -507,7 +507,7 @@ void geometry_information::generate_floorshapes_for(int id, cell *c, int siid, i
|
|||
}
|
||||
}
|
||||
|
||||
else if(arb::in() || aperiodic) {
|
||||
else if(arb::in() || aperiodic || arcm::in() || IRREGULAR) {
|
||||
vector<hyperpoint> actual;
|
||||
for(int j=0; j<cor; j++)
|
||||
actual.push_back(get_corner_position(c, j));
|
||||
|
|
2
game.cpp
2
game.cpp
|
@ -347,6 +347,8 @@ EX void pushThumper(const movei& mi) {
|
|||
if(w == waThumperOn)
|
||||
explode = 2;
|
||||
}
|
||||
if(w == waExplosiveBarrel && cto->wall == waMineMine)
|
||||
explode = 2;
|
||||
destroyTrapsOn(cto);
|
||||
if(cto->wall == waOpenPlate || cto->wall == waClosePlate) {
|
||||
toggleGates(cto, cto->wall);
|
||||
|
|
14
geom-exp.cpp
14
geom-exp.cpp
|
@ -152,11 +152,8 @@ void validity_info() {
|
|||
EX bool showquotients;
|
||||
|
||||
string validclasses[4] = {" (X)", " (½)", "", " (!)"};
|
||||
|
||||
EX void ge_land_selection() {
|
||||
cmode = sm::SIDE | sm::MAYDARK;
|
||||
gamescreen();
|
||||
|
||||
EX void gen_landvisited() {
|
||||
if(cheater) for(int i=0; i<landtypes; i++) landvisited[i] = true;
|
||||
|
||||
for(int i=0; i<landtypes; i++)
|
||||
|
@ -177,6 +174,13 @@ EX void ge_land_selection() {
|
|||
landvisited[laCamelot] |= hiitemsMax(treasureType(laCamelot)) >= 1;
|
||||
landvisited[laCA] = true;
|
||||
landvisited[laAsteroids] = true;
|
||||
}
|
||||
|
||||
EX void ge_land_selection() {
|
||||
cmode = sm::SIDE | sm::MAYDARK;
|
||||
gamescreen();
|
||||
|
||||
gen_landvisited();
|
||||
|
||||
dialog::init(XLAT("select the starting land"));
|
||||
if(dialog::infix != "") mouseovers = dialog::infix;
|
||||
|
@ -1109,7 +1113,7 @@ EX void showEuclideanMenu() {
|
|||
}
|
||||
|
||||
dialog::addBoolItem(XLAT("pattern"), specialland == laCanvas, 'p');
|
||||
if(specialland == laCanvas) dialog::lastItem().value = patterns::whichCanvas;
|
||||
if(specialland == laCanvas) dialog::lastItem().value = ccolor::which->name;
|
||||
dialog::add_action_push(patterns::showPrePattern);
|
||||
validity_info();
|
||||
if(WDIM == 3) {
|
||||
|
|
|
@ -576,8 +576,6 @@ EX void add_wall(int i, const vector<hyperpoint>& h) {
|
|||
static constexpr ld hcrossf7 = 0.620672, hexf7 = 0.378077, tessf7 = 1.090550, hexhexdist7 = 0.566256;
|
||||
#endif
|
||||
|
||||
EX bool scale_used() { return (shmup::on && geometry == gNormal && BITRUNCATED) ? (cheater || autocheat) : true; }
|
||||
|
||||
EX bool is_subcube_based(eVariation var) {
|
||||
return among(var, eVariation::subcubes, eVariation::dual_subcubes, eVariation::bch, eVariation::bch_oct);
|
||||
}
|
||||
|
@ -784,13 +782,13 @@ void geometry_information::prepare_basics() {
|
|||
if(msphere && geuclid) scalefactor *= (1 + vid.depth);
|
||||
if(msphere && ghyperbolic) scalefactor *= sinh(1 + vid.depth);
|
||||
|
||||
if(scale_used()) {
|
||||
if(true) {
|
||||
scalefactor *= vid.creature_scale;
|
||||
orbsize *= vid.creature_scale;
|
||||
}
|
||||
|
||||
zhexf = BITRUNCATED ? hexf : crossf* .55;
|
||||
if(scale_used()) zhexf *= vid.creature_scale;
|
||||
zhexf *= vid.creature_scale;
|
||||
if(WDIM == 2 && GDIM == 3) zhexf *= 1.5, orbsize *= 1.2;
|
||||
|
||||
if(cgi.emb->is_euc_in_hyp()) {
|
||||
|
@ -1314,7 +1312,7 @@ EX string cgi_string() {
|
|||
V("RS:", fts(geom3::euclid_embed_rotate));
|
||||
}
|
||||
|
||||
if(scale_used()) V("CS", fts(vid.creature_scale));
|
||||
if(vid.creature_scale != 1) V("CS", fts(vid.creature_scale));
|
||||
|
||||
if(WDIM == 3) V("HTW", fts(vid.height_width));
|
||||
|
||||
|
|
31
goldberg.cpp
31
goldberg.cpp
|
@ -813,6 +813,15 @@ EX namespace gp {
|
|||
screens = g;
|
||||
}
|
||||
|
||||
EX bool check_whirl_set(loc xy) {
|
||||
if(!check_limits(xy)) {
|
||||
addMessage(XLAT("Outside of the supported limits"));
|
||||
return false;
|
||||
}
|
||||
whirl_set(xy);
|
||||
return true;
|
||||
}
|
||||
|
||||
string helptext() {
|
||||
return XLAT(
|
||||
"Goldberg polyhedra are obtained by adding extra hexagons to a dodecahedron. "
|
||||
|
@ -887,10 +896,11 @@ EX namespace gp {
|
|||
}
|
||||
|
||||
dialog::addBreak(100);
|
||||
int max_goldberg = (1<<GOLDBERG_BITS)/2 - 1;
|
||||
dialog::addSelItem("x", its(config.first), 'x');
|
||||
dialog::add_action([] { dialog::editNumber(config.first, 0, 8, 1, 1, "x", helptext()); });
|
||||
dialog::add_action([max_goldberg] { dialog::editNumber(config.first, 0, max_goldberg, 1, 1, "x", helptext()); });
|
||||
dialog::addSelItem("y", its(config.second), 'y');
|
||||
dialog::add_action([] { dialog::editNumber(config.second, 0, 8, 1, 1, "y", helptext()); });
|
||||
dialog::add_action([max_goldberg] { dialog::editNumber(config.second, 0, max_goldberg, 1, 1, "y", helptext()); });
|
||||
|
||||
if(!check_limits(config))
|
||||
dialog::addInfo(XLAT("Outside of the supported limits"));
|
||||
|
@ -973,24 +983,24 @@ EX namespace gp {
|
|||
auto p = univ_param();
|
||||
if(S3 == 3 && !UNTRUNCATED) {
|
||||
println(hlog, "set param to ", p * loc(1,1));
|
||||
whirl_set(p * loc(1, 1));
|
||||
if(!check_whirl_set(p * loc(1, 1))) return;
|
||||
set_variation(eVariation::untruncated);
|
||||
start_game();
|
||||
config = human_representation(univ_param());
|
||||
}
|
||||
else if(S3 == 4 && !UNRECTIFIED) {
|
||||
whirl_set(p * loc(1, 1));
|
||||
if(!check_whirl_set(p * loc(1, 1))) return;
|
||||
set_variation(eVariation::unrectified);
|
||||
start_game();
|
||||
config = human_representation(univ_param());
|
||||
}
|
||||
else if(S3 == 3 && UNTRUNCATED) {
|
||||
println(hlog, "whirl_set to ", (p * loc(1,1)) / 3);
|
||||
whirl_set((p * loc(1,1)) / 3);
|
||||
if(!check_whirl_set((p * loc(1,1)) / 3)) return;
|
||||
config = human_representation(univ_param());
|
||||
}
|
||||
else if(S3 == 4 && UNRECTIFIED) {
|
||||
whirl_set((p * loc(1,1)) / 2);
|
||||
if(!check_whirl_set((p * loc(1,1)) / 2)) return;
|
||||
config = human_representation(univ_param());
|
||||
}
|
||||
});
|
||||
|
@ -1259,6 +1269,7 @@ EX namespace gp {
|
|||
}
|
||||
|
||||
hrmap_inverse() {
|
||||
underlying_map = nullptr;
|
||||
if(0) {
|
||||
println(hlog, "making ucgi");
|
||||
dynamicval<eVariation> gva(variation, variation_for(param));
|
||||
|
@ -1431,11 +1442,17 @@ EX namespace gp {
|
|||
return C0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
EX hrmap* new_inverse() { return new hrmap_inverse; }
|
||||
|
||||
hrmap_inverse* inv_map() { return (hrmap_inverse*)currentmap; }
|
||||
|
||||
EX bool inverse_pseudohept(cell *c) {
|
||||
cell *c1 = inv_map()->mapping[c];
|
||||
if(!c1) return false;
|
||||
return UIU(pseudohept(c1));
|
||||
}
|
||||
|
||||
EX hrmap* get_underlying_map() { return inv_map()->underlying_map; }
|
||||
EX cell* get_mapped(cell *c) { return inv_map()->get_mapped(c, 0); }
|
||||
EX int untruncated_shift(cell *c) { return inv_map()->shift[c]; }
|
||||
|
|
105
graph.cpp
105
graph.cpp
|
@ -769,11 +769,12 @@ EX shiftmatrix face_the_player(const shiftmatrix V) {
|
|||
if(nonisotropic) return shiftless(spin_towards(unshift(V), dummy, C0, 2, 0));
|
||||
#if CAP_VR
|
||||
if(vrhr::enabled) {
|
||||
shiftpoint h = tC0(V);
|
||||
shiftpoint h = tC0(V);
|
||||
hyperpoint uh = unshift(h);
|
||||
return shiftless(cspin90(1, 2) * lrspintox(cspin90(2, 1) * uh) * xpush(hdist0(uh)) * cspin90(0, 2) * spin270());
|
||||
return shiftless(cspin90(1, 2) * rspintox(cspin90(2, 1) * uh) * xpush(hdist0(uh)) * cspin90(0, 2) * spin270());
|
||||
}
|
||||
#endif
|
||||
|
||||
return rgpushxto0(tC0(V));
|
||||
}
|
||||
|
||||
|
@ -846,12 +847,42 @@ EX void draw_ascii(const shiftmatrix& V, char glyph, color_t col, ld size) {
|
|||
string s = s0 + glyph;
|
||||
int id = isize(ptds);
|
||||
if(WDIM == 2 && GDIM == 3)
|
||||
queuestrn(V * lzpush(cgi.FLOOR - cgi.scalefactor * size / 4), size, s, darkenedby(col, darken), 0);
|
||||
queuestrn(V * lzpush(cgi.FLOOR - cgi.scalefactor * size / 4), size * mapfontscale / 100, s, darkenedby(col, darken), 0);
|
||||
else
|
||||
queuestrn(V, 1, s, darkenedby(col, darken), GDIM == 3 ? 0 : 2);
|
||||
queuestrn(V, mapfontscale / 100, s, darkenedby(col, darken), GDIM == 3 ? 0 : 2);
|
||||
while(id < isize(ptds)) ptds[id++]->prio = PPR::MONSTER_BODY;
|
||||
}
|
||||
|
||||
EX void queue_goal_text(shiftpoint P1, ld sizemul, const string& s, color_t color) {
|
||||
#if CAP_VR
|
||||
if(vrhr::enabled) {
|
||||
auto e = inverse_exp(P1);
|
||||
e = e * 3 / hypot_d(GDIM, e);
|
||||
auto T = face_the_player(shiftless(rgpushxto0(direct_exp(e))));
|
||||
queuestrn(T, sizemul * mapfontscale / 100, s, color);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
queuestr(P1, vid.fsize * sizemul, s, color);
|
||||
}
|
||||
|
||||
EX bool mark_compass(cell *c, shiftpoint& P1) {
|
||||
cell *c1 = c ? findcompass(c) : NULL;
|
||||
if(!c1) return false;
|
||||
|
||||
shiftmatrix P = ggmatrix(c1);
|
||||
P1 = tC0(P);
|
||||
|
||||
if(isPlayerOn(c)) {
|
||||
queue_goal_text(P1, 2, "X", 0x10100 * int(128 + 100 * sintick(150)));
|
||||
// queuestr(V, 1, its(compassDist(c)), 0x10101 * int(128 - 100 * sin(ticks / 150.)), 1);
|
||||
queue_goal_text(P1, 1, its(-compassDist(c)), 0x10101 * int(128 - 100 * sintick(150)));
|
||||
addauraspecial(P1, 0xFF0000, 0);
|
||||
addradar(P, 'X', iinf[itCompass].color, 0xFF, true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
EX bool drawItemType(eItem it, cell *c, const shiftmatrix& V, color_t icol, int pticks, bool hidden) {
|
||||
if(!it) return false;
|
||||
char xch = iinf[it].glyph;
|
||||
|
@ -953,18 +984,8 @@ EX bool drawItemType(eItem it, cell *c, const shiftmatrix& V, color_t icol, int
|
|||
else
|
||||
#endif
|
||||
if(1) {
|
||||
cell *c1 = c ? findcompass(c) : NULL;
|
||||
if(c1) {
|
||||
shiftmatrix P = ggmatrix(c1);
|
||||
shiftpoint P1 = tC0(P);
|
||||
|
||||
if(isPlayerOn(c)) {
|
||||
queuestr(P1, 2*vid.fsize, "X", 0x10100 * int(128 + 100 * sintick(150)));
|
||||
// queuestr(V, 1, its(compassDist(c)), 0x10101 * int(128 - 100 * sin(ticks / 150.)), 1);
|
||||
queuestr(P1, vid.fsize, its(-compassDist(c)), 0x10101 * int(128 - 100 * sintick(150)));
|
||||
addauraspecial(P1, 0xFF0000, 0);
|
||||
}
|
||||
|
||||
shiftpoint P1;
|
||||
if(mark_compass(c, P1)) {
|
||||
V2 = V * lrspintox(inverse_shift(V, P1));
|
||||
}
|
||||
else V2 = V;
|
||||
|
@ -3103,15 +3124,15 @@ EX bool drawMonster(const shiftmatrix& Vparam, int ct, cell *c, color_t col, col
|
|||
col = mirrorcolor(geometry == gElliptic ? det(Vs.T) < 0 : mirr);
|
||||
if(!mouseout() && !nospins && GDIM == 2) {
|
||||
shiftpoint P2 = Vs * inverse_shift(inmirrorcount ? ocwtV : cwtV, mouseh);
|
||||
queuestr(P2, 10, "x", 0xFF00);
|
||||
}
|
||||
queuestr(P2, 10*mapfontscale/100, "x", 0xFF00);
|
||||
}
|
||||
if(!nospins && flipplayer) Vs = Vs * lpispin();
|
||||
|
||||
|
||||
res = res && drawMonsterType(moMimic, c, Vs, col, footphase, asciicol);
|
||||
drawPlayerEffects(Vs, Vparam, c, c->monst);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// illusions face randomly
|
||||
|
||||
else if(c->monst == moIllusion) {
|
||||
|
@ -3235,7 +3256,7 @@ EX bool drawMonster(const shiftmatrix& Vparam, int ct, cell *c, color_t col, col
|
|||
hyperpoint h = inverse_shift(ocwtV, mouseh);
|
||||
if(flipplayer) h = lpispin() * h;
|
||||
shiftpoint P2 = Vs * h;
|
||||
queuestr(P2, 10, "x", 0xFF00);
|
||||
queuestr(P2, mapfontscale / 10, "x", 0xFF00);
|
||||
}
|
||||
|
||||
if(hide_player()) {
|
||||
|
@ -3573,7 +3594,7 @@ void draw_movement_arrows(cell *c, const transmatrix& V, int df) {
|
|||
transmatrix T = iso_inverse(Centered) * rgpushxto0(Centered * tC0(V)) * lrspintox(Centered*tC0(V)) * spin(-sd * M_PI/S7) * xpush(0.2);
|
||||
|
||||
if(vid.axes >= 5)
|
||||
queuestr(shiftless(T), keysize, s0 + key, col >> 8, 1);
|
||||
queuestr(shiftless(T), keysize * mapfontscale / 100, s0 + key, col >> 8, 1);
|
||||
|
||||
else
|
||||
queuepoly(shiftless(T), cgi.shArrow, col);
|
||||
|
@ -3581,7 +3602,7 @@ void draw_movement_arrows(cell *c, const transmatrix& V, int df) {
|
|||
else if(!confusingGeometry()) break;
|
||||
}
|
||||
}
|
||||
if(keylist != "") queuestr(shiftless(V), keysize, keylist, col >> 8, 1);
|
||||
if(keylist != "") queuestr(shiftless(V), keysize * mapfontscale / 100, keylist, col >> 8, 1);
|
||||
}
|
||||
|
||||
EX int celldistAltPlus(cell *c) { return 1000000 + celldistAlt(c); }
|
||||
|
@ -4008,12 +4029,16 @@ EX int colorhash(color_t i) {
|
|||
return (i * 0x471211 + i*i*0x124159 + i*i*i*0x982165) & 0xFFFFFF;
|
||||
}
|
||||
|
||||
EX int mine_opacity = 255;
|
||||
|
||||
EX bool isWall3(cell *c, color_t& wcol) {
|
||||
if(c->wall == waRose) { wcol = gradient(0, wcol, -5 - 5 * (7-rosephase), sintick(50 * (8 - rosephase)), 1); }
|
||||
if(isWall(c)) return true;
|
||||
if(c->wall == waChasm && c->land == laMemory && (anyshiftclick || !(cgflags & qFRACTAL))) { wcol = 0x606000; return true; }
|
||||
if(c->wall == waInvisibleFloor) return false;
|
||||
// if(chasmgraph(c)) return true;
|
||||
if(among(c->wall, waMirror, waCloud, waMineUnknown, waMineMine)) return true;
|
||||
if(among(c->wall, waMirror, waCloud)) return true;
|
||||
if(among(c->wall, waMineUnknown, waMineMine) && mine_opacity == 255) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -4056,6 +4081,8 @@ EX color_t transcolor(cell *c, cell *c2, color_t wcol) {
|
|||
}
|
||||
if(among(c->wall, waRubble, waDeadfloor2) && !snakelevel(c2)) return darkena3(winf[c->wall].color, 0, 0x40);
|
||||
if(c->wall == waMagma && c2->wall != waMagma) return darkena3(magma_color(lavatide(c, -1)/4), 0, 0x80);
|
||||
if(among(c->wall, waMineUnknown, waMineMine) && !among(c2->wall, waMineMine, waMineUnknown) && mine_opacity > 0 && mine_opacity < 255)
|
||||
return 0xFFFFFF00 | mine_opacity;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -4761,7 +4788,7 @@ EX void drawMarkers() {
|
|||
#if CAP_QUEUE
|
||||
if(haveMount())
|
||||
for (const shiftmatrix& V : hr::span_at(current_display->all_drawn_copies, dragon::target)) {
|
||||
queuestr(V, 1, "X",
|
||||
queuestr(V, mapfontscale/100, "X",
|
||||
gradient(0, iinf[itOrbDomination].color, -1, sintick(dragon::whichturn == turncount ? 75 : 150), 1));
|
||||
}
|
||||
#endif
|
||||
|
@ -4773,31 +4800,31 @@ EX void drawMarkers() {
|
|||
using namespace yendor;
|
||||
if(yii < isize(yi) && !yi[yii].found) {
|
||||
cell *keycell = NULL;
|
||||
int i;
|
||||
for(i=0; i<YDIST; i++)
|
||||
int last_i = 0;
|
||||
for(int i=0; i<YDIST; i++)
|
||||
if(yi[yii].path[i]->cpdist <= get_sightrange_ambush()) {
|
||||
keycell = yi[yii].path[i];
|
||||
keycell = yi[yii].path[i]; last_i = i;
|
||||
}
|
||||
if(keycell) {
|
||||
for(; i<YDIST; i++) {
|
||||
for(int i = last_i+1; i<YDIST; i++) {
|
||||
cell *c = yi[yii].path[i];
|
||||
if(inscreenrange(c))
|
||||
keycell = c;
|
||||
}
|
||||
shiftpoint H = tC0(ggmatrix(keycell));
|
||||
#if CAP_QUEUE
|
||||
queuestr(H, 2*vid.fsize, "X", 0x10101 * int(128 + 100 * sintick(150)));
|
||||
queue_goal_text(H, 2, "X", 0x10101 * int(128 + 100 * sintick(150)));
|
||||
int cd = celldistance(yi[yii].key(), cwt.at);
|
||||
if(cd == DISTANCE_UNKNOWN) for(int i2 = 0; i2<YDIST; i2++) {
|
||||
int cd2 = celldistance(cwt.at, yi[yii].path[i2]);
|
||||
if(cd2 != DISTANCE_UNKNOWN) {
|
||||
cd = cd2 + (YDIST-1-i2);
|
||||
println(hlog, "i2 = ", i2, " cd = ", celldistance(cwt.at, keycell));
|
||||
}
|
||||
}
|
||||
queuestr(H, vid.fsize, its(cd), 0x10101 * int(128 - 100 * sintick(150)));
|
||||
queue_goal_text(H, 1, its(cd), 0x10101 * int(128 - 100 * sintick(150)));
|
||||
#endif
|
||||
addauraspecial(H, iinf[itOrbYendor].color, 0);
|
||||
addradar(ggmatrix(keycell), 'X', iinf[itKey].color, kind_outline(itKey), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4930,9 +4957,10 @@ EX void drawMarkers() {
|
|||
}
|
||||
if(items[itOrbAir] && mouseover->cpdist > 1) {
|
||||
cell *c1 = mouseover;
|
||||
int dir = c1->monst == moVoidBeast ? -1 : 1;
|
||||
for(int it=0; it<10; it++) {
|
||||
int di;
|
||||
auto mib = blowoff_destination(c1, di);
|
||||
auto mib = blowoff_destination_dir(c1, di, dir);
|
||||
if(!mib.proper()) break;
|
||||
auto& c2 = mib.t;
|
||||
shiftmatrix T1 = ggmatrix(c1);
|
||||
|
@ -4993,12 +5021,12 @@ EX void draw_flash(struct flashdata& f, const shiftmatrix& V, bool& kill) {
|
|||
int r = 2;
|
||||
apply_neon(col, r);
|
||||
if(GDIM == 3 || sphere)
|
||||
queuestr(V, (1 - tim * 1. / f.size) * f.angle, f.text, col, r);
|
||||
queuestr(V, (1 - tim * 1. / f.size) * f.angle * mapfontscale / 100, f.text, col, r);
|
||||
else if(!kill) {
|
||||
shiftpoint h = tC0(V);
|
||||
if(hdist0(h) > .1) {
|
||||
transmatrix V2 = rspintox(h.h) * xpush(hdist0(h.h) * (1 / (1 - tim * 1. / f.size)));
|
||||
queuestr(shiftless(V2, h.shift), f.angle, f.text, col, r);
|
||||
queuestr(shiftless(V2, h.shift), f.angle * mapfontscale / 100, f.text, col, r);
|
||||
}
|
||||
}
|
||||
if(static_bubbles) {
|
||||
|
@ -5644,6 +5672,7 @@ EX bool just_refreshing;
|
|||
|
||||
EX int menu_darkening = 2;
|
||||
EX bool centered_menus = false;
|
||||
EX bool show_turns = false;
|
||||
|
||||
EX void gamescreen() {
|
||||
|
||||
|
@ -5770,13 +5799,15 @@ EX void normalscreen() {
|
|||
cmode = sm::NORMAL | sm::DOTOUR | sm::CENTER;
|
||||
if(viewdists && show_distance_lists) cmode |= sm::SIDE | sm::MAYDARK;
|
||||
gamescreen(); drawStats();
|
||||
if(nomenukey || ISMOBILE)
|
||||
if(show_turns)
|
||||
displayButton(vid.xres-8, vid.yres-vid.fsize, "t:" + its(turncount), 'v', 16);
|
||||
else if(nomenukey || ISMOBILE)
|
||||
;
|
||||
#if CAP_TOUR
|
||||
else if(tour::on)
|
||||
displayButton(vid.xres-8, vid.yres-vid.fsize, XLAT("(ESC) tour menu"), SDLK_ESCAPE, 16);
|
||||
else
|
||||
#endif
|
||||
else
|
||||
displayButton(vid.xres-8, vid.yres-vid.fsize, XLAT("(v) menu"), 'v', 16);
|
||||
keyhandler = handleKeyNormal;
|
||||
|
||||
|
|
52
help.cpp
52
help.cpp
|
@ -236,12 +236,12 @@ EX void buildCredits() {
|
|||
help += XLAT(
|
||||
"special thanks to the following people for their bug reports, feature requests, porting, and other help:\n\n%1\n\n",
|
||||
"Konstantin Stupnik, ortoslon, chrysn, Adam Borowski, Damyan Ivanov, Ryan Farnsley, mcobit, Darren Grey, tricosahedron, Maciej Chojecki, Marek Čtrnáct, "
|
||||
"wonderfullizardofoz, Piotr Migdał, tehora, Michael Heerdegen, Sprite Guard, zelda0x181e, Vipul, snowyowl0, Patashu, phenomist, Alan Malloy, Tom Fryers, Sinquetica, _monad, CtrlAltDestroy, jruderman, "
|
||||
"wonderfullizardofoz, Piotr Migdał, Tehora Rogue, Michael Heerdegen, Sprite Guard, zelda0x181e, Vipul, snowyowl0, Patashu, phenomist, Alan Malloy, Tom Fryers, Sinquetica, _monad, CtrlAltDestroy, jruderman, "
|
||||
"Kojiguchi Kazuki, baconcow, Alan, SurelyYouJest, hotdogPi, DivisionByZero, xXxWeedGokuxXx, jpystynen, Dmitry Marakasov, Alexandre Moine, Arthur O'Dwyer, "
|
||||
"Triple_Agent_AAA, bluetailedgnat, Allalinor, Shitford, KittyTac, Christopher King, KosGD, TravelDemon, Bubbles, rdococ, frozenlake, MagmaMcFry, "
|
||||
"Snakebird Priestess, roaringdragon2, Stopping Dog, bengineer8, Sir Light IJIJ, ShadeBlade, Saplou, shnourok, Ralith, madasa, 6% remaining, Chimera245, Remik Pi, alien foxcat thing, "
|
||||
"Piotr Grochowski, Ann, still-flow, tyzone, Paradoxica, LottieRatWorld, aismallard, albatross, EncodedSpirit, Jacob Mandelson, CrashTuvai, cvoight, jennlbw, Kali Ranya, spiritbackup, Dylan, L_Lord, AntiRogue, "
|
||||
"masonlgreen"
|
||||
"masonlgreen, A human, Pasu4"
|
||||
);
|
||||
#ifdef EXTRALICENSE
|
||||
help += EXTRALICENSE;
|
||||
|
@ -553,6 +553,20 @@ EX string generateHelpForItem(eItem it) {
|
|||
return help;
|
||||
}
|
||||
|
||||
void mine_dialog() {
|
||||
cmode = sm::SIDE;
|
||||
gamescreen();
|
||||
dialog::init("Minefield graphics");
|
||||
add_edit(numerical_minefield);
|
||||
add_edit(mine_zero_display);
|
||||
add_edit(mine_opacity);
|
||||
add_edit(mine_hollow);
|
||||
add_edit(mine_markers);
|
||||
dialog::addItem(XLAT("minefield colors"), 'c');
|
||||
dialog::add_action_push([] { edit_color_table(minecolors); });
|
||||
dialog::display();
|
||||
}
|
||||
|
||||
void addMinefieldExplanation(string& s) {
|
||||
|
||||
s += XLAT(
|
||||
|
@ -568,7 +582,7 @@ void addMinefieldExplanation(string& s) {
|
|||
s += XLAT("Known mines may be marked by touching while in drag mode. Your allies won't step on marked mines.");
|
||||
#endif
|
||||
|
||||
help_extensions.push_back(help_extension{'n', XLAT("toggle numerical display"), [] () { numerical_minefield = !numerical_minefield; }});
|
||||
help_extensions.push_back(help_extension{'c', XLAT("configure"), [] () { pushScreen(mine_dialog); } });
|
||||
}
|
||||
|
||||
EX string generateHelpForWall(eWall w) {
|
||||
|
@ -700,10 +714,12 @@ void add_reqs(eLand l, string& s) {
|
|||
#define COND(x,y) s += (y);
|
||||
#define ITEMS_TOTAL(list, z) \
|
||||
{ int now = 0; string t = "("; for(eItem i: list) { if(t!="(") t += " | "; t += XLATN(iinf[i].name); now += items[i]; } t += ")"; s += XLAT("Treasure required: %1 x %2.\n", its(z), t); buteol(s, now, z); }
|
||||
#define INMODE(x) ;
|
||||
#define ACCONLY(z) s += XLAT("Accessible only from %the1.\n", z);
|
||||
#define ACCONLY2(z,x) s += XLAT("Accessible only from %the1 or %the2.\n", z, x);
|
||||
#define ACCONLY3(z,y,x) s += XLAT("Accessible only from %the1, %2, or %3.\n", z, y, x);
|
||||
#define ACCONLYF(z) s += XLAT("Accessible only from %the1 (until finished).\n", z);
|
||||
#define IFINGAME(land, ok, fallback) if(isLandIngame(land)) { ok } else { s += XLAT("Alternative rule when %the1 is not in the game:\n", land); fallback }
|
||||
#include "content.cpp"
|
||||
|
||||
case landtypes: return;
|
||||
|
@ -881,9 +897,9 @@ EX void describeMouseover() {
|
|||
if(shmup::on)
|
||||
out += " (" + its(c->landparam)+")";
|
||||
else {
|
||||
bool b = c->landparam >= tide[(turncount-1) % tidalsize];
|
||||
bool b = c->landparam >= tide[turncount % tidalsize];
|
||||
int t = 1;
|
||||
for(; t < 1000 && b == (c->landparam >= tide[(turncount+t-1) % tidalsize]); t++) ;
|
||||
for(; t < 1000 && b == (c->landparam >= tide[(turncount+t) % tidalsize]); t++) ;
|
||||
if(b)
|
||||
out += " (" + turnstring(t) + XLAT(" to surface") + ")";
|
||||
else
|
||||
|
@ -892,7 +908,7 @@ EX void describeMouseover() {
|
|||
}
|
||||
#if CAP_FIELD
|
||||
else if(c->land == laVolcano) {
|
||||
int id = lavatide(c, -1)/4;
|
||||
int id = lavatide(c, 0)/4;
|
||||
if(id < 96/4)
|
||||
out += " (" + turnstring(96/4-id) + XLAT(" to go cold") + ")";
|
||||
else
|
||||
|
@ -1087,16 +1103,7 @@ EX void describeMouseover() {
|
|||
#endif
|
||||
}
|
||||
|
||||
EX void showHelp() {
|
||||
cmode = sm::HELP | sm::DOTOUR | sm::DARKEN;
|
||||
getcstat = SDLK_ESCAPE;
|
||||
if(help == "HELPFUN") {
|
||||
help_delegate();
|
||||
return;
|
||||
}
|
||||
|
||||
gamescreen();
|
||||
string help2;
|
||||
EX void addHelpWithTitle() {
|
||||
if(help[0] == '@') {
|
||||
int iv = help.find("\t");
|
||||
int id = help.find("\n");
|
||||
|
@ -1107,6 +1114,19 @@ EX void showHelp() {
|
|||
dialog::init("help", forecolor, 120, 100);
|
||||
dialog::addHelp(help);
|
||||
}
|
||||
}
|
||||
|
||||
EX void showHelp() {
|
||||
cmode = sm::HELP | sm::DOTOUR | sm::DARKEN;
|
||||
getcstat = SDLK_ESCAPE;
|
||||
if(help == "HELPFUN") {
|
||||
help_delegate();
|
||||
return;
|
||||
}
|
||||
|
||||
gamescreen();
|
||||
string help2;
|
||||
addHelpWithTitle();
|
||||
|
||||
bool in_list = false;
|
||||
|
||||
|
|
12
history.cpp
12
history.cpp
|
@ -457,6 +457,11 @@ EX namespace history {
|
|||
dynamicval<bool> di(inHighQual, true);
|
||||
|
||||
renderbuffer glbuf(bandfull, bandfull, vid.usingGL);
|
||||
glbuf.make_surface(); if(!glbuf.srf) {
|
||||
addMessage(XLAT("Could not create an image of that size."));
|
||||
return;
|
||||
}
|
||||
|
||||
vid.xres = vid.yres = bandfull;
|
||||
glbuf.enable(); current_display->radius = bandhalf;
|
||||
calcparam();
|
||||
|
@ -480,7 +485,8 @@ EX namespace history {
|
|||
};
|
||||
|
||||
if(!band) {
|
||||
addMessage("Could not create an image of that size.");
|
||||
addMessage(XLAT("Could not create an image of that size."));
|
||||
return;
|
||||
}
|
||||
else {
|
||||
|
||||
|
@ -528,6 +534,10 @@ EX namespace history {
|
|||
len -= bandsegment; xpos -= bandsegment;
|
||||
seglen = min(int(len), bandsegment);
|
||||
band = SDL_CreateRGBSurface(SDL_SWSURFACE, seglen, bandfull,32,0,0,0,0);
|
||||
if(!band) {
|
||||
addMessage(XLAT("Could not create an image of that size."));
|
||||
return;
|
||||
}
|
||||
goto drawsegment;
|
||||
}
|
||||
xpos += bwidth;
|
||||
|
|
|
@ -144,7 +144,10 @@ template<class T, class U> void hread(hstream& hs, map<T,U>& a) {
|
|||
template<class C, class C1, class... CS> void hwrite(hstream& hs, const C& c, const C1& c1, const CS&... cs) { hwrite(hs, c); hwrite(hs, c1, cs...); }
|
||||
template<class C, class C1, class... CS> void hread(hstream& hs, C& c, C1& c1, CS&... cs) { hread(hs, c); hread(hs, c1, cs...); }
|
||||
|
||||
struct hstream_exception : hr_exception {};
|
||||
struct hstream_exception : hr_exception {
|
||||
hstream_exception() : hr_exception("hstream_exception") {}
|
||||
hstream_exception(const std::string &s) : hr_exception(s) {}
|
||||
};
|
||||
|
||||
struct fhstream : hstream {
|
||||
FILE *f;
|
||||
|
|
6
hud.cpp
6
hud.cpp
|
@ -705,12 +705,12 @@ EX void drawStats() {
|
|||
if(peace::on) vers += " peace";
|
||||
if(racing::on) vers += " racing";
|
||||
if(daily::on) vers += " strange";
|
||||
if(bow::weapon && bow::style == bow::cbBull) vers += " b/bull";
|
||||
if(bow::weapon && bow::style == bow::cbGeodesic) vers += " b/geo";
|
||||
if(bow::crossbow_mode()) vers += " b/" + bow::bowName[bow::style];
|
||||
if(land_structure != default_land_structure())
|
||||
vers += land_structure_name(true);
|
||||
vers += " " + land_structure_name(true);
|
||||
if(princess::challenge) vers += " Princess";
|
||||
if(randomPatternsMode) vers += " RPM";
|
||||
if(use_custom_land_list) vers += " custom";
|
||||
|
||||
if(geometry != gNormal || !BITRUNCATED)
|
||||
vers = vers + " " + full_geometry_name();
|
||||
|
|
|
@ -132,9 +132,7 @@
|
|||
#include "rogueviz/rogueviz-all.cpp"
|
||||
#endif
|
||||
|
||||
#if CAP_DAILY
|
||||
#include "private/daily.cpp"
|
||||
#else
|
||||
#if !CAP_DAILY
|
||||
namespace hr { namespace daily { bool on; int historical; } }
|
||||
#endif
|
||||
|
||||
|
|
17
hyper.h
17
hyper.h
|
@ -13,8 +13,8 @@
|
|||
#define _HYPER_H_
|
||||
|
||||
// version numbers
|
||||
#define VER "13.0a"
|
||||
#define VERNUM_HEX 0xAA01
|
||||
#define VER "13.0i"
|
||||
#define VERNUM_HEX 0xAA09
|
||||
|
||||
#include "sysconfig.h"
|
||||
|
||||
|
@ -221,15 +221,6 @@ void addMessage(string s, char spamtype = 0);
|
|||
|
||||
#define NUMWITCH 7
|
||||
|
||||
// achievements
|
||||
|
||||
#define LB_YENDOR_CHALLENGE 40
|
||||
#define LB_PURE_TACTICS 41
|
||||
#define NUMLEADER 90
|
||||
#define LB_PURE_TACTICS_SHMUP 49
|
||||
#define LB_PURE_TACTICS_COOP 50
|
||||
#define LB_RACING 81
|
||||
|
||||
#if ISMOBILE || ISWEB || ISPANDORA || 1
|
||||
typedef double ld;
|
||||
#define LDF "%lf"
|
||||
|
@ -262,6 +253,7 @@ struct projection_configuration {
|
|||
ld clip_min, clip_max;
|
||||
ld halfplane_scale;
|
||||
ld collignon_parameter;
|
||||
ld offside, offside2;
|
||||
ld aitoff_parameter, miller_parameter, loximuthal_parameter, winkel_parameter;
|
||||
bool show_hyperboloid_flat;
|
||||
bool collignon_reflected;
|
||||
|
@ -565,7 +557,7 @@ typedef function<int(struct cell*)> cellfunction;
|
|||
// passable flags
|
||||
|
||||
#define SAGEMELT .1
|
||||
#define PT(x, y) ((tactic::on || quotient == 2 || daily::on) ? (y) : inv::on ? min(2*(y),x) : (x))
|
||||
#define PT(x, y) rebalance_treasure(x, y, c->land)
|
||||
#define ROCKSNAKELENGTH 50
|
||||
#define WORMLENGTH 15
|
||||
#define PRIZEMUL 7
|
||||
|
@ -779,6 +771,7 @@ enum orbAction { roMouse, roKeyboard, roCheck, roMouseForce, roMultiCheck, roMul
|
|||
#define pmodel (pconf.model)
|
||||
|
||||
static constexpr int DISTANCE_UNKNOWN = 127;
|
||||
static constexpr int DISTANCE_UNKNOWN_BIG = 99999999;
|
||||
|
||||
template<class T, class U> int addHook(hookset<T>& m, int prio, U&& hook) {
|
||||
return m.add(prio, static_cast<U&&>(hook));
|
||||
|
|
28
hypgraph.cpp
28
hypgraph.cpp
|
@ -1362,6 +1362,21 @@ EX void apply_other_model(shiftpoint H_orig, hyperpoint& ret, eModel md) {
|
|||
makeband(H_orig, ret, [] (ld& x, ld& y) { x *= cos_auto(y); });
|
||||
break;
|
||||
|
||||
case mdPolar: {
|
||||
models::scr_to_ori(H);
|
||||
H = xpush(pconf.offside) * H;
|
||||
ld zlev = find_zlev(H);
|
||||
ld d = hdist0(H);
|
||||
ld df, zf;
|
||||
hypot_zlev(zlev, d, df, zf);
|
||||
ret[0] = -atan2(H) / M_PI;
|
||||
ret[1] = (d - pconf.offside2) / M_PI;
|
||||
ret[2] = zf;
|
||||
ret[3] = 1;
|
||||
models::ori_to_scr(ret);
|
||||
break;
|
||||
}
|
||||
|
||||
case mdEquidistant: case mdEquiarea: case mdEquivolume: {
|
||||
if(vrhr::rendering() && GDIM == 3 && pmodel == mdEquidistant) {
|
||||
ret = inverse_exp(H_orig);
|
||||
|
@ -1452,7 +1467,10 @@ EX void apply_other_model(shiftpoint H_orig, hyperpoint& ret, eModel md) {
|
|||
|
||||
case mdSpiral: {
|
||||
cld z;
|
||||
if(hyperbolic || sphere) makeband(H_orig, ret, band_conformal);
|
||||
if(hyperbolic || sphere) {
|
||||
makeband(H_orig, ret, band_conformal);
|
||||
models::scr_to_ori(ret);
|
||||
}
|
||||
else ret = H;
|
||||
z = cld(ret[0], ret[1]) * models::spiral_multiplier;
|
||||
|
||||
|
@ -1477,6 +1495,7 @@ EX void apply_other_model(shiftpoint H_orig, hyperpoint& ret, eModel md) {
|
|||
if(pconf.skiprope)
|
||||
ret = mobius(ret, pconf.skiprope, 1);
|
||||
}
|
||||
models::ori_to_scr(ret);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -3004,6 +3023,7 @@ EX void draw_boundary(int w) {
|
|||
hyperpoint ret = point2(real(z), imag(z));
|
||||
ret = mobius(ret, pconf.skiprope, 1);
|
||||
ret *= current_display->radius;
|
||||
models::ori_to_scr(ret);
|
||||
curvepoint(ret);
|
||||
}
|
||||
queuecurve(shiftless(Id), ringcolor, 0, p).flags |= POLY_ALWAYS_IN;
|
||||
|
@ -3197,7 +3217,7 @@ EX bool do_draw(cell *c) {
|
|||
EX ld extra_generation_distance = 99;
|
||||
|
||||
// returns false if limited
|
||||
bool limited_generation(cell *c) {
|
||||
EX bool limited_generation(cell *c) {
|
||||
if(c->mpdist <= 7) return true;
|
||||
if(cells_generated > vid.cells_generated_limit) return false;
|
||||
setdist(c, 7, c);
|
||||
|
@ -3207,7 +3227,11 @@ bool limited_generation(cell *c) {
|
|||
|
||||
EX int min_cells_drawn = 50;
|
||||
|
||||
EX hookset<int(cell*,const shiftmatrix&)> hooks_do_draw;
|
||||
|
||||
EX bool do_draw(cell *c, const shiftmatrix& T) {
|
||||
int h = callhandlers(0, hooks_do_draw, c, T);
|
||||
if(h) return h > 0;
|
||||
|
||||
if(WDIM == 3) {
|
||||
// do not care about cells outside of the track
|
||||
|
|
|
@ -538,7 +538,7 @@ EX void shift_view_portal(hyperpoint H) {
|
|||
if(b) maxv = t; else minv = t;
|
||||
shift_view(H * -t * scale);
|
||||
}
|
||||
println(hlog, "maxv = ", maxv);
|
||||
// println(hlog, "maxv = ", maxv);
|
||||
shift_view(H * maxv * scale);
|
||||
check_portal_movement();
|
||||
shift_view_portal(H * (1 - maxv) * scale);
|
||||
|
|
106
irregular.cpp
106
irregular.cpp
|
@ -402,10 +402,7 @@ bool step(int delta) {
|
|||
if(notfound) { status[4] = XLAT("cells badly paired: %1", its(notfound)); runlevel = 0; break; }
|
||||
|
||||
int heptas = 0;
|
||||
for(auto p: cells_of_heptagon) {
|
||||
printf("%p: %d\n", hr::voidp(p.first), isize(p.second));
|
||||
heptas++;
|
||||
}
|
||||
for(auto p: cells_of_heptagon) heptas++;
|
||||
|
||||
if(heptas != isize(all)) {
|
||||
status[4] = XLAT("cells not covered: %1", its(isize(all) - heptas));
|
||||
|
@ -770,7 +767,7 @@ EX int celldist(cell *c, bool alts) {
|
|||
return hi.celldists[alts][cells[cellindex[c]].localindex];
|
||||
}
|
||||
|
||||
eGeometry orig_geometry;
|
||||
eGeometry orig_geometry, base_geometry;
|
||||
|
||||
void start_game_on_created_map() {
|
||||
popScreen();
|
||||
|
@ -807,6 +804,47 @@ bool save_map(const string& fname) {
|
|||
return true;
|
||||
}
|
||||
|
||||
vector<ld> float_order;
|
||||
|
||||
EX void save_map_bin(hstream& f) {
|
||||
if(!base) { f.write<short>(-1); return; }
|
||||
auto& all = base->allcells();
|
||||
int origcells = 0;
|
||||
for(cellinfo& ci: cells)
|
||||
if(ci.generation == 0)
|
||||
origcells++;
|
||||
f.write<short> (base_geometry);
|
||||
f.write<short> (isize(all));
|
||||
f.write<short> (origcells);
|
||||
int foi = 0;
|
||||
|
||||
auto check_float_order = [&] (ld x) {
|
||||
if(foi >= isize(float_order)) {
|
||||
float_order.push_back(x);
|
||||
f.write<ld>(x);
|
||||
}
|
||||
else if(abs(float_order[foi] - x) > 1e-6) {
|
||||
println(hlog, float_order[foi], " vs ", x, " : abs difference is ", abs(float_order[foi] - x));
|
||||
float_order[foi] = x;
|
||||
}
|
||||
f.write<ld>(float_order[foi++]);
|
||||
};
|
||||
|
||||
for(auto h: all) {
|
||||
origcells = 0;
|
||||
for(auto i: cells_of_heptagon[h->master])
|
||||
if(cells[i].generation == 0)
|
||||
origcells++;
|
||||
f.write<short> (origcells);
|
||||
for(auto i: cells_of_heptagon[h->master]) if(cells[i].generation == 0) {
|
||||
auto &ci = cells[i];
|
||||
check_float_order(ci.p[0]);
|
||||
check_float_order(ci.p[1]);
|
||||
check_float_order(ci.p[LDIM]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool load_map(const string &fname) {
|
||||
fhstream f(fname, "rt");
|
||||
if(!f.f) return false;
|
||||
|
@ -839,6 +877,52 @@ bool load_map(const string &fname) {
|
|||
return true;
|
||||
}
|
||||
|
||||
EX void load_map_bin(hstream& f) {
|
||||
auto& all = base->allcells();
|
||||
eGeometry g = (eGeometry) f.get<short>();
|
||||
if(int(g) == -1) return;
|
||||
int sa = f.get<short>();
|
||||
cellcount = f.get<short>();
|
||||
|
||||
if(g != geometry) throw hstream_exception("bad geometry");
|
||||
if(sa != isize(all)) throw hstream_exception("bad size of all");
|
||||
density = cellcount * 1. / isize(all);
|
||||
|
||||
cells.clear();
|
||||
float_order.clear();
|
||||
|
||||
for(auto h: all) {
|
||||
int q = f.get<short>();
|
||||
if(q < 0 || q > cellcount) throw hstream_exception("incorrect quantity");
|
||||
while(q--) {
|
||||
cells.emplace_back();
|
||||
cellinfo& s = cells.back();
|
||||
s.patterndir = -1;
|
||||
double a, b, c;
|
||||
a = f.get<ld>();
|
||||
b = f.get<ld>();
|
||||
c = f.get<ld>();
|
||||
float_order.push_back(a);
|
||||
float_order.push_back(b);
|
||||
float_order.push_back(c);
|
||||
s.p = hpxyz(a, b, c);
|
||||
s.p = normalize(s.p);
|
||||
for(auto c0: all) s.relmatrices[c0] = calc_relative_matrix(c0, h, s.p);
|
||||
s.owner = h;
|
||||
}
|
||||
}
|
||||
|
||||
make_cells_of_heptagon();
|
||||
runlevel = 2;
|
||||
}
|
||||
|
||||
EX void load_map_full(hstream& f) {
|
||||
init();
|
||||
load_map_bin(f);
|
||||
while(runlevel < 10) step(1000);
|
||||
start_game_on_created_map();
|
||||
}
|
||||
|
||||
void cancel_map_creation() {
|
||||
base = NULL;
|
||||
runlevel = 0;
|
||||
|
@ -950,7 +1034,7 @@ void show_gridmaker() {
|
|||
};
|
||||
}
|
||||
|
||||
EX void visual_creator() {
|
||||
EX void init() {
|
||||
stop_game();
|
||||
orig_geometry = geometry;
|
||||
switch(geometry) {
|
||||
|
@ -966,13 +1050,19 @@ EX void visual_creator() {
|
|||
break;
|
||||
}
|
||||
|
||||
base_geometry = geometry;
|
||||
variation = eVariation::pure;
|
||||
start_game();
|
||||
if(base) delete base;
|
||||
base = currentmap;
|
||||
base_config = euc::eu;
|
||||
drawthemap();
|
||||
cellcount = int(isize(base->allcells()) * density + .5);
|
||||
gridmaking = true;
|
||||
drawthemap();
|
||||
}
|
||||
|
||||
EX void visual_creator() {
|
||||
init();
|
||||
pushScreen(show_gridmaker);
|
||||
runlevel = 0;
|
||||
gridmaking = true;
|
||||
|
@ -1015,7 +1105,7 @@ int readArgs() {
|
|||
else if(argis("-irrload")) {
|
||||
PHASE(3);
|
||||
restart_game();
|
||||
visual_creator();
|
||||
init();
|
||||
showstartmenu = false;
|
||||
shift();
|
||||
load_map(args());
|
||||
|
|
21
items.cpp
21
items.cpp
|
@ -16,8 +16,13 @@ EX array<int, ittypes> items;
|
|||
|
||||
EX map<modecode_t, array<int, ittypes> > hiitems;
|
||||
|
||||
EX bool pickable_from_water(eItem it) {
|
||||
return among(it, itOrbFish, itOrbAether);
|
||||
}
|
||||
|
||||
EX bool cannotPickupItem(cell *c, bool telekinesis) {
|
||||
return itemHidden(c) && !telekinesis && !(isWatery(c) && markOrb(itOrbFish));
|
||||
if(pickable_from_water(c->item) && isWatery(c)) return false;
|
||||
return itemHidden(c) && !telekinesis && !(isWatery(c) && (markOrb(itOrbFish) || markOrb(itOrbAether)));
|
||||
}
|
||||
|
||||
EX bool canPickupItemWithMagnetism(cell *c, cell *from) {
|
||||
|
@ -39,9 +44,9 @@ EX bool doPickupItemsWithMagnetism(cell *c) {
|
|||
if(!isNeighbor(c, c4) && c3->item && !c4->item && passable(c4, c3, ZERO)) {
|
||||
changes.ccell(c3);
|
||||
changes.ccell(c4);
|
||||
c4->item = c3->item;
|
||||
moveEffect(movei(c3, c4, (cw+j).spin), moDeadBird);
|
||||
c3->item = itNone;
|
||||
moveItem(c3, c4, false);
|
||||
animateMovement(match(c3, c4), LAYER_BOAT);
|
||||
moveEffect(movei(c4, c4, NODIR), moDeadBird);
|
||||
markOrb(itCurseRepulsion);
|
||||
}
|
||||
}
|
||||
|
@ -57,8 +62,12 @@ EX bool doPickupItemsWithMagnetism(cell *c) {
|
|||
}
|
||||
else if(c3->item == itOrbSafety || c3->item == itBuggy || c3->item == itBuggy2)
|
||||
csaf = c3;
|
||||
else if(markOrb(itOrbMagnetism))
|
||||
else if(markOrb(itOrbMagnetism)) {
|
||||
eItem it = c3->item;
|
||||
collectItem(c3, c3, false);
|
||||
if(!c3->item)
|
||||
animate_item_throw(c3, c, it);
|
||||
}
|
||||
}
|
||||
if(csaf)
|
||||
return collectItem(csaf, csaf, false);
|
||||
|
@ -733,7 +742,7 @@ EX void collectMessage(cell *c2, eItem which) {
|
|||
|
||||
EX bool itemHiddenFromSight(cell *c) {
|
||||
return isWatery(c) && !items[itOrbInvis] && !(items[itOrbFish] && playerInWater())
|
||||
&& !(shmup::on && shmup::boatAt(c));
|
||||
&& !(shmup::on && shmup::boatAt(c)) && !(c->cpdist <= 1 && playerInWater());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
118
landgen.cpp
118
landgen.cpp
|
@ -171,8 +171,8 @@ EX void place_elemental_wall(cell *c) {
|
|||
else if(c->land == laEEarth) c->wall = waStone;
|
||||
}
|
||||
|
||||
// automatically adjust monster generation for 3D geometries
|
||||
EX int hrand_monster(int x) {
|
||||
// automatically adjust monster generation for 3D geometries and custom difficulty
|
||||
EX int hrand_monster_in(eLand l, int x) {
|
||||
// dual geometry mode is much harder, so generate less monsters to balance it
|
||||
if(dual::state) x *= 3;
|
||||
// in 3D monster generation depends on the sight range
|
||||
|
@ -180,9 +180,15 @@ EX int hrand_monster(int x) {
|
|||
int t = isize(gmatrix);
|
||||
if(t > 500) x = int(((long long)(x)) * t / 500);
|
||||
}
|
||||
if(use_custom_land_list) {
|
||||
x = x * 100 / custom_land_difficulty[l];
|
||||
if(x == 0) x = 1;
|
||||
}
|
||||
return hrand(x);
|
||||
}
|
||||
|
||||
#define hrand_monster(x) hrand_monster_in(c->land, x)
|
||||
|
||||
EX bool is_zebra_trapdoor(cell *c) {
|
||||
if(euclid && closed_or_bounded) return false;
|
||||
#if CAP_ARCM
|
||||
|
@ -195,7 +201,6 @@ EX bool is_zebra_trapdoor(cell *c) {
|
|||
else if(PURE && reg3::exact_rules()) switch(geometry) {
|
||||
case gSpace534: {
|
||||
if(c->master->fieldval == 0) return true;
|
||||
forCellCM(c1, c) if(c1->master->fieldval == 0) return true;
|
||||
return false;
|
||||
}
|
||||
case gSpace435: {
|
||||
|
@ -280,6 +285,23 @@ EX void gen_baby_tortoise(cell *c) {
|
|||
tortoise::babymap[c] = tortoise::getb(c) ^ tortoise::getRandomBits();
|
||||
}
|
||||
|
||||
EX int rebalance_treasure(int x, int y, eLand l) {
|
||||
int res = ((tactic::on || quotient == 2 || daily::on) ? (y) : inv::on ? min(2*(y),x) : (x));
|
||||
if(use_custom_land_list) res = (res * custom_land_treasure[l] + 50) / 100;
|
||||
res *= ls::ls_mul();
|
||||
return res;
|
||||
}
|
||||
|
||||
EX eItem random_curse() {
|
||||
return pick(itCurseWeakness, itCurseDraining, itCurseWater, itCurseFatigue, itCurseRepulsion, itCurseGluttony);
|
||||
}
|
||||
|
||||
EX void clear_item(cell *c) {
|
||||
if(c->item == itOrbWater && c->wall == waStrandedBoat)
|
||||
c->wall = waNone;
|
||||
c->item = itNone;
|
||||
}
|
||||
|
||||
EX void giantLandSwitch(cell *c, int d, cell *from) {
|
||||
bool fargen = d == 9;
|
||||
switch(c->land) {
|
||||
|
@ -536,7 +558,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
|
|||
// no Plates or Trapdoors in the Princess cell
|
||||
if(d < 3 && (c->wall == waClosePlate || c->wall == waOpenPlate || c->wall == waTrapdoor))
|
||||
c->wall = waNone;
|
||||
if(d > 1) c->item = itNone;
|
||||
if(d > 1) clear_item(c);
|
||||
// the Princess herself
|
||||
if(d == 0) {
|
||||
c->monst = moPrincess;
|
||||
|
@ -634,9 +656,9 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
|
|||
c->wall = waCavewall;
|
||||
else c->wall = waCavefloor;
|
||||
}
|
||||
else if(a4 || arcm::in() || cryst)
|
||||
else if(a4 || arcm::in() || cryst || bt::in() || S3 >= OINF)
|
||||
c->wall = hrand(100) < 50 ? waCavefloor : waCavewall;
|
||||
else if(!BITRUNCATED) {
|
||||
else if(!BITRUNCATED && geometry != gOctagon) {
|
||||
if(polarb50(c))
|
||||
c->wall = waCavewall;
|
||||
else c->wall = waCavefloor;
|
||||
|
@ -743,7 +765,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
|
|||
}
|
||||
}
|
||||
// seal entrances to the Land of Power.
|
||||
if(d == 7 && ctof(c)) {
|
||||
if(d == 7 && ctof(c) && land_structure != lsLandscape) {
|
||||
bool onwall = false;
|
||||
for(int i=0; i<c->type; i++) if(c->move(i) && c->move(i)->land == laBarrier)
|
||||
onwall = true;
|
||||
|
@ -753,13 +775,16 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
|
|||
cell *c3 = c2->modmove(c->c.spin(i) + 3);
|
||||
if(!c3) continue;
|
||||
if(c3->land != laPower && c3->land != laBarrier)
|
||||
if(c2->wall != waFire && c2->wall != waGlass) {
|
||||
if(c2->wall != waEternalFire && c2->wall != waGlass) {
|
||||
if(isFire(c)) c->monst = moWitchWinter;
|
||||
else if(c->wall == waGlass) c->monst = moWitchGhost;
|
||||
else c->monst = moEvilGolem;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(d == 7 && land_structure == lsLandscape) {
|
||||
forCellEx(c2, c) if(c2->land != laPower) c->wall = waEternalFire;
|
||||
}
|
||||
ONEMPTY {
|
||||
if(hrand(5000+50*items[itPower]) < 1200) {
|
||||
eItem powerorbs[6] = {
|
||||
|
@ -811,7 +836,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
|
|||
}
|
||||
else if(WDIM == 3 && hyperbolic && !bt::in())
|
||||
c->wall = (c->master->zebraval & 2) ? waVinePlant : waNone;
|
||||
else if(a4 || sphere || arcm::in())
|
||||
else if(a4 || sphere || arcm::in() || bt::in() || S3 >= OINF)
|
||||
c->wall = hrand(100) < 50 ? waNone : waVinePlant;
|
||||
else {
|
||||
int v = emeraldval(c);
|
||||
|
@ -832,6 +857,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
|
|||
forCellCM(c2, c) if(emeraldval(c2) == (v^1))
|
||||
c->wall = waVinePlant;
|
||||
}
|
||||
if(weirdhyperbolic && cellHalfvine(c)) c->wall = waNone;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -924,11 +950,17 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
|
|||
|
||||
case laTrollheim:
|
||||
if(fargen) {
|
||||
if(hrand(50000) < (ls::tame_chaos() ? 1000: ls::any_chaos() ?50:5) && c->wall != waBarrier && celldist(c) >= 7 && !safety && !peace::on) {
|
||||
int freq =
|
||||
land_structure == lsVineWalls ? 10000 :
|
||||
ls::wall_chaos() ? 2500 :
|
||||
ls::tame_chaos() ? 1000 :
|
||||
ls::any_chaos() ? 50 :
|
||||
5;
|
||||
if(hrand(50000) < freq && c->wall != waBarrier && celldist(c) >= 7 && !safety && !peace::on) {
|
||||
bool okay = true;
|
||||
forCellCM(c2, c) forCellCM(c3, c2) forCellCM(c4, c3) forCellCM(c5, c4) {
|
||||
cell *cx = ls::any_chaos() ? c3 : c5;
|
||||
if(cx->land != laTrollheim && cx->land != laNone)
|
||||
if(cx->land != laTrollheim && cx->land != laNone && !ls::hv_structure())
|
||||
okay = false;
|
||||
if(cx->bardir != NODIR) okay = false;
|
||||
}
|
||||
|
@ -1226,7 +1258,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
|
|||
if(fargen) {
|
||||
if(hrand(500) < 15)
|
||||
createArrowTrapAt(c, laTerracotta);
|
||||
if(pseudohept(c) && hrand(100) < 40 && c->wall == waNone && !racing::on) {
|
||||
if(pseudohept_r(c) && hrand(100) < 40 && c->wall == waNone && !racing::on) {
|
||||
c->wall = waTerraWarrior;
|
||||
c->wparam = terracotta::randterra ? 0 : 3 + hrand(3);
|
||||
if(hrand(100) < items[itTerra]-10)
|
||||
|
@ -1268,7 +1300,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
|
|||
if(d == 8) {
|
||||
bool ok = c->landparam == 0;
|
||||
forCellEx(c2, c) if(c2->landparam) ok = false;
|
||||
if(ok && hrand(doCross ?450:15000) < 20 + (2 * items[itMutant] + yendor::hardness()) && !safety) {
|
||||
if(ok && hrand(doCross ?450:15000) < (20 + (2 * items[itMutant] + yendor::hardness())) * ls::ls_mul_big() && !safety) {
|
||||
if(!peace::on) c->item = itMutant;
|
||||
c->landparam = items[itMutant] + 5 + hrand(11);
|
||||
c->wall = waNone;
|
||||
|
@ -1296,6 +1328,12 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
|
|||
break;
|
||||
|
||||
case laHalloween:
|
||||
if(!closed_or_bounded) {
|
||||
ONEMPTY {
|
||||
if(hrand(1000) < PT(20, 20)) c->item = itTreat;
|
||||
if(hrand(1000) < 20) c->wall = waChasm;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case laWildWest:
|
||||
|
@ -1503,7 +1541,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
|
|||
if(fargen) {
|
||||
if(randomPatternsMode)
|
||||
c->wall = RANDPAT ? ((RANDPATV(laCrossroads) || RANDPATV(laCrossroads2)) ? waAncientGrave : waFreshGrave) : waNone;
|
||||
else if(pseudohept(c))
|
||||
else if(pseudohept_r(c))
|
||||
c->wall = hrand(5) ? waAncientGrave : waFreshGrave;
|
||||
}
|
||||
ONEMPTY {
|
||||
|
@ -1536,7 +1574,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
|
|||
c->move(i)->wall = waNone;
|
||||
}
|
||||
}
|
||||
if(pseudohept(c) && hrand(2)) c->wall = waColumn;
|
||||
if(pseudohept_r(c) && hrand(2)) c->wall = waColumn;
|
||||
}
|
||||
}
|
||||
ONEMPTY {
|
||||
|
@ -2047,7 +2085,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
|
|||
|
||||
case laHunting:
|
||||
if(d == 7 && c->land == laHunting && !racing::on && !safety && !reptilecheat) {
|
||||
if(hrand(1000) < 20) {
|
||||
if(hrand(1000) < 20 * ls::ls_mul_big()) {
|
||||
if(openplains(c)) {
|
||||
if(hrand(2) == 0) {
|
||||
if(!items[itHunting]) {
|
||||
|
@ -2255,11 +2293,11 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
|
|||
c->monst = moMonkey;
|
||||
else if(hrand_monster(80000) < 5 + items[itRuby] + yendor::hardness())
|
||||
c->monst = moEagle;
|
||||
else if(pseudohept(c) && c != currentmap->gamestart() && hrand_monster(4000) < 300 + items[itRuby] && !c->monst) {
|
||||
else if(pseudohept_r(c) && c != currentmap->gamestart() && hrand_monster(4000) < (300 + items[itRuby]) * ls::ls_mul_big() && !c->monst) {
|
||||
int hardchance = items[itRuby] + yendor::hardness();
|
||||
if(hardchance > 25) hardchance = 25;
|
||||
bool hardivy = hrand(100) < hardchance;
|
||||
if((cgflags & qFRACTAL) ? buildIvy(c, 0, 2) : hat::in() ? buildIvy(c, 0, 4) : (hardivy ? buildIvy(c, 1, 9) : buildIvy(c, 0, c->type)) && !peace::on)
|
||||
if(land_structure == lsVineWalls ? buildIvy(c, 0, 2) : (cgflags & qFRACTAL) ? buildIvy(c, 0, 2) : hat::in() ? buildIvy(c, 0, 4) : (hardivy ? buildIvy(c, 1, 9) : buildIvy(c, 0, c->type)) && !peace::on)
|
||||
c->item = itRuby;
|
||||
}
|
||||
}
|
||||
|
@ -2299,7 +2337,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
|
|||
int d = -celldistAlt(c);
|
||||
if(hrand_monster(2500) < items[itMutant2] + yendor::hardness() - 10 && !reptilecheat)
|
||||
c->monst = moRedFox;
|
||||
else if(hrand(100 + d) < d && !reptilecheat)
|
||||
else if(d > 0 && hrand(100 + d) < d && !reptilecheat)
|
||||
c->item = itMutant2;
|
||||
}
|
||||
}
|
||||
|
@ -2378,7 +2416,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
|
|||
if(hrand(1500) < PT(30 + kills[moHexDemon] + kills[moAltDemon] + kills[moMonk] + kills[moPair] + kills[moCrusher], 100) && notDippingFor(itRuins)) {
|
||||
c->item = itRuins;
|
||||
forCellEx(c2, c) if(c2->monst == moMonk)
|
||||
c->item = itNone;
|
||||
clear_item(c);
|
||||
}
|
||||
if(hrand_monster(7000) < kf && !c->monst) {
|
||||
c->monst = genRuinMonster(c);
|
||||
|
@ -2516,7 +2554,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
|
|||
if(d == 7) {
|
||||
c->wall = waNone;
|
||||
|
||||
c->item = itNone; c->monst = moNone;
|
||||
clear_item(c); c->monst = moNone;
|
||||
|
||||
if(hrand(100) < 25)
|
||||
c->wall = hrand(2) ? waBigTree : waSmallTree;
|
||||
|
@ -2557,7 +2595,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
|
|||
treasure_rate += variant::features[i].rate_change;
|
||||
variant::features[i].build(c);
|
||||
}
|
||||
if(hrand(2000 - PT(kills[moVariantWarrior] * 5, 250)) < treasure_rate && !c->wall && !c->monst)
|
||||
if(hrand(max(100, 2000 - PT(kills[moVariantWarrior] * 5, 250))) < treasure_rate && !c->wall && !c->monst)
|
||||
c->item = itVarTreasure;
|
||||
}
|
||||
if(d == 7 && c->wall == waTrapdoor) {
|
||||
|
@ -2628,7 +2666,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
|
|||
}
|
||||
|
||||
case laCursed: {
|
||||
if(fargen) {
|
||||
if(fargen && c->wall != waRubble) {
|
||||
c->wall = waStone;
|
||||
for(int i=0; i<3; i++) {
|
||||
auto ew = [i] (cell *c1) {
|
||||
|
@ -2664,7 +2702,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
|
|||
c->wall = waStone;
|
||||
else {
|
||||
c->monst = moHexer;
|
||||
c->item = pick(itCurseWeakness, itCurseDraining, itCurseWater, itCurseFatigue, itCurseRepulsion, itCurseGluttony);
|
||||
c->item = random_curse();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -2882,13 +2920,37 @@ EX void share_land(cell *c, cell *c2) {
|
|||
c->land = c2->land;
|
||||
}
|
||||
|
||||
EX void set_land_for_geometry(cell *c) {
|
||||
// odd landscape_div are better
|
||||
EX int landscape_div = 25;
|
||||
|
||||
EX void set_land_for_geometry(cell *c) {
|
||||
if(!c->land && isize(currentlands)) {
|
||||
if(land_structure == lsTotalChaos) {
|
||||
setland(c, random_land());
|
||||
return;
|
||||
}
|
||||
if(land_structure == lsLandscape) {
|
||||
if(landscape_div <= 0) landscape_div = 1;
|
||||
array<int, 3> a;
|
||||
for(int i=0; i<3; i++) a[i] = getCdata(c, i);
|
||||
auto& ld = landscape_div;
|
||||
auto ld2 = ld * 2;
|
||||
int sh = 0;
|
||||
for(int i=0; i<3; i++) {
|
||||
int x = a[i];
|
||||
x = gmod(x, ld2);
|
||||
if(x >= ld) sh += x - ld;
|
||||
else sh += ld - 1 - x;
|
||||
}
|
||||
for(int i=0; i<3; i++) {
|
||||
if(sh * 2 < ld * 3) a[i] = gdiv(a[i], ld2)*2+1;
|
||||
else a[i] = gdiv(a[i]+ld, ld2)*2;
|
||||
}
|
||||
eLand& l = landscape_lands[make_array(a[0], a[1], a[2])];
|
||||
if(l == laNone) l = random_land();
|
||||
setland(c, l);
|
||||
return;
|
||||
}
|
||||
/* note: Nil patched chaos done in setLandNil */
|
||||
if(ls::patched_chaos() && (cgflags & qFRACTAL)) {
|
||||
share_land(c, fractal_rep(c));
|
||||
|
@ -2990,7 +3052,7 @@ EX void setdist(cell *c, int d, cell *from) {
|
|||
}
|
||||
#endif
|
||||
|
||||
if(!c->land && from && (WDIM == 3 || !among(from->land, laBarrier, laElementalWall, laHauntedWall, laOceanWall)) && !quotient && ls::chaoticity() < 60) {
|
||||
if(!c->land && from && (WDIM == 3 || !among(from->land, laBarrier, laElementalWall, laHauntedWall, laOceanWall)) && !quotient && ls::chaoticity() < 60 && land_structure != lsLandscape) {
|
||||
if(!hasbardir(c)) setland(c, from->land);
|
||||
}
|
||||
if(c->land == laTemple && ls::any_order()) setland(c, laRlyeh);
|
||||
|
@ -3013,7 +3075,7 @@ EX void setdist(cell *c, int d, cell *from) {
|
|||
}
|
||||
|
||||
if(d == BARLEV && c->land == laCanvas) {
|
||||
color_t col = patterns::generateCanvas(c);
|
||||
color_t col = ccolor::generateCanvas(c);
|
||||
c->landparam = col;
|
||||
c->wall = canvas_default_wall;
|
||||
if((GDIM == 3 || geom3::flipped) && (col & 0x1000000)) c->wall = waWaxWall;
|
||||
|
@ -3139,4 +3201,6 @@ EX void setdist(cell *c, int d, cell *from) {
|
|||
#endif
|
||||
}
|
||||
|
||||
#undef hrand_monster
|
||||
|
||||
}
|
||||
|
|
229
landlock.cpp
229
landlock.cpp
|
@ -81,7 +81,7 @@ EX eLand firstland = laIce;
|
|||
EX eLand specialland = laIce;
|
||||
|
||||
#if HDR
|
||||
enum eLandStructure { lsNiceWalls, lsChaos, lsPatchedChaos, lsTotalChaos, lsChaosRW, lsWallChaos, lsSingle, lsNoWalls, lsHorodisks, lsVoronoi, lsGUARD };
|
||||
enum eLandStructure { lsNiceWalls, lsChaos, lsPatchedChaos, lsTotalChaos, lsChaosRW, lsWallChaos, lsSingle, lsNoWalls, lsHorodisks, lsVoronoi, lsLandscape, lsCrossWalls, lsVineWalls, lsCursedWalls, lsGUARD };
|
||||
#endif
|
||||
|
||||
EX eLandStructure land_structure;
|
||||
|
@ -90,9 +90,9 @@ EX namespace ls {
|
|||
|
||||
EX bool single() { return land_structure == lsSingle; }
|
||||
|
||||
EX bool any_chaos() { return among(land_structure, lsChaos, lsPatchedChaos, lsWallChaos, lsTotalChaos, lsChaosRW); }
|
||||
EX bool any_chaos() { return among(land_structure, lsChaos, lsPatchedChaos, lsWallChaos, lsTotalChaos, lsChaosRW, lsCrossWalls, lsVineWalls, lsCursedWalls, lsLandscape); }
|
||||
EX bool std_chaos() { return land_structure == lsChaos; }
|
||||
EX bool wall_chaos() { return land_structure == lsWallChaos; }
|
||||
EX bool wall_chaos() { return among(land_structure, lsWallChaos, lsCrossWalls, lsVineWalls, lsCursedWalls); }
|
||||
EX bool patched_chaos() { return land_structure == lsPatchedChaos; }
|
||||
|
||||
EX bool any_order() { return among(land_structure, lsNiceWalls, lsNoWalls, lsHorodisks, lsVoronoi); }
|
||||
|
@ -110,12 +110,33 @@ EX int chaoticity() {
|
|||
if(land_structure == lsChaosRW) return 80;
|
||||
if(land_structure == lsPatchedChaos) return 60;
|
||||
if(land_structure == lsChaos) return 40;
|
||||
if(land_structure == lsLandscape) return 35;
|
||||
if(land_structure == lsWallChaos) return 30;
|
||||
if(land_structure == lsCrossWalls) return 32;
|
||||
if(land_structure == lsCursedWalls) return 34;
|
||||
if(land_structure == lsVoronoi) return 20;
|
||||
if(land_structure == lsSingle) return 0;
|
||||
return 10;
|
||||
}
|
||||
|
||||
/** a multiplier to make stuff more frequent in Wall Chaos and Cross Wall Chaos: treasure */
|
||||
EX int ls_mul() {
|
||||
if(land_structure == lsWallChaos) return 2;
|
||||
if(land_structure == lsCrossWalls) return 3;
|
||||
if(land_structure == lsVineWalls) return 3;
|
||||
if(land_structure == lsCursedWalls) return 3;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** a multiplier to make stuff more frequent in Wall Chaos and Cross Wall Chaos: even bigger */
|
||||
EX int ls_mul_big() {
|
||||
if(land_structure == lsWallChaos) return 5;
|
||||
if(land_structure == lsCrossWalls) return 10;
|
||||
if(land_structure == lsVineWalls) return 10;
|
||||
if(land_structure == lsCursedWalls) return 10;
|
||||
return 1;
|
||||
}
|
||||
|
||||
EX bool tame_chaos() { return any_chaos() && chaoticity() < 35; }
|
||||
EX }
|
||||
|
||||
|
@ -139,8 +160,16 @@ EX string land_structure_name(bool which) {
|
|||
return XLAT("horodisks");
|
||||
case lsVoronoi:
|
||||
return XLAT("ideal Voronoi");
|
||||
case lsLandscape:
|
||||
return XLAT("landscape");
|
||||
case lsNoWalls:
|
||||
return XLAT("wall-less");
|
||||
case lsCrossWalls:
|
||||
return XLAT("excessive crossing walls");
|
||||
case lsVineWalls:
|
||||
return XLAT("regular walls");
|
||||
case lsCursedWalls:
|
||||
return XLAT("cursed walls");
|
||||
default:
|
||||
return "error structure";
|
||||
}
|
||||
|
@ -151,6 +180,8 @@ EX void fix_land_structure_choice() {
|
|||
if(land_structure != lsTotalChaos && land_structure != lsChaosRW)
|
||||
land_structure = lsSingle;
|
||||
}
|
||||
if(land_structure == lsLandscape && !geometry_supports_cdata())
|
||||
land_structure = lsChaosRW;
|
||||
if(tactic::on || princess::challenge)
|
||||
land_structure = lsSingle;
|
||||
if(yendor::on)
|
||||
|
@ -159,6 +190,12 @@ EX void fix_land_structure_choice() {
|
|||
land_structure = lsNoWalls;
|
||||
if(!nice_walls_available() && land_structure == lsWallChaos)
|
||||
land_structure = lsChaos;
|
||||
if(!nice_walls_available() && land_structure == lsCrossWalls)
|
||||
land_structure = lsChaos;
|
||||
if(land_structure == lsVineWalls && (geometry != gNormal || !BITRUNCATED))
|
||||
land_structure = lsNiceWalls;
|
||||
if(land_structure == lsCursedWalls && (geometry != gNormal || !BITRUNCATED))
|
||||
land_structure = lsNiceWalls;
|
||||
if(ls::hv_structure() && (!hyperbolic || bt::in() || quotient))
|
||||
land_structure = lsSingle;
|
||||
if(walls_not_implemented() && among(land_structure, lsChaos, lsNoWalls))
|
||||
|
@ -224,6 +261,8 @@ EX bool landUnlocked(eLand l) {
|
|||
#define ACCONLY2(x,y)
|
||||
#define ACCONLY3(x,y,z)
|
||||
#define ACCONLYF(x)
|
||||
#define IFINGAME(land, ok, fallback) if(isLandIngame(land)) { ok } else { fallback }
|
||||
#define INMODE(x) if(x) return true;
|
||||
#include "content.cpp"
|
||||
|
||||
case landtypes: return false;
|
||||
|
@ -245,6 +284,10 @@ EX void countHyperstoneQuest(int& i1, int& i2) {
|
|||
i1 = 0; i2 = 0;
|
||||
generateLandList(isLandIngame);
|
||||
for(eLand l: landlist) {
|
||||
// no treasure
|
||||
if(l == laCA) continue;
|
||||
// same treasure, so count only once
|
||||
if(l == laMirrorOld && isLandIngame(laMirror)) continue;
|
||||
eItem ttype = treasureType(l);
|
||||
if(!required_for_hyperstones(ttype)) continue;
|
||||
i2++; if(items[ttype] >= R10) i1++;
|
||||
|
@ -376,7 +419,7 @@ EX eLand pickluck(eLand l1, eLand l2) {
|
|||
} */
|
||||
|
||||
EX eLand getNewSealand(eLand old) {
|
||||
while(true) {
|
||||
for(int it=0; it<100; it++) {
|
||||
eLand p = pick(laOcean, pick(laCaribbean, laLivefjord, laWarpSea, laKraken, laDocks));
|
||||
if(p == laKraken && !landUnlocked(p)) continue;
|
||||
if(p == laKraken && peace::on) continue;
|
||||
|
@ -385,6 +428,7 @@ EX eLand getNewSealand(eLand old) {
|
|||
if(!isLandIngame(p)) continue;
|
||||
return p;
|
||||
}
|
||||
return old;
|
||||
}
|
||||
|
||||
EX bool createOnSea(eLand old) {
|
||||
|
@ -551,7 +595,8 @@ EX eLand getNewLand(eLand old) {
|
|||
// the intermediate lands
|
||||
if(all_unlocked || gold() >= R30) {
|
||||
tab[cnt++] = laCrossroads;
|
||||
tab[cnt++] = (geometry || ls::hv_structure()) ? laMirrorOld : laMirror;
|
||||
tab[cnt++] = laMirrorOld;
|
||||
tab[cnt++] = laMirror;
|
||||
tab[cnt++] = laOcean;
|
||||
tab[cnt++] = laLivefjord;
|
||||
if(all_unlocked || kills[moVizier]) tab[cnt++] = laEmerald;
|
||||
|
@ -560,6 +605,11 @@ EX eLand getNewLand(eLand old) {
|
|||
tab[cnt++] = laDocks;
|
||||
}
|
||||
|
||||
tab[cnt++] = laHalloween;
|
||||
tab[cnt++] = laWildWest;
|
||||
tab[cnt++] = laAsteroids;
|
||||
tab[cnt++] = laCA;
|
||||
|
||||
// the advanced lands
|
||||
if(all_unlocked || gold() >= R60) {
|
||||
tab[cnt++] = laCrossroads;
|
||||
|
@ -606,7 +656,7 @@ EX eLand getNewLand(eLand old) {
|
|||
if(isTrollLand(old)) LIKELY tab[cnt++] = laTrollheim;
|
||||
if(old == laTrollheim) for(int i=0; i<landtypes; i++) {
|
||||
eLand l2 = eLand(i);
|
||||
if(isTrollLand(l2)) LIKELY tab[cnt++] = l2;
|
||||
if(isTrollLand(l2) && landUnlocked(l2)) LIKELY tab[cnt++] = l2;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -625,13 +675,24 @@ EX eLand getNewLand(eLand old) {
|
|||
|
||||
if(ls::horodisk_structure() && tortoise::seek()) LIKELY tab[cnt++] = laTortoise;
|
||||
|
||||
eLand n = old;
|
||||
while(incompatible(n, old) || !isLandIngame(n)) {
|
||||
n = tab[hrand(cnt)];
|
||||
if(weirdhyperbolic && specialland == laCrossroads4 && isCrossroads(n))
|
||||
n = laCrossroads4;
|
||||
int idx = 0;
|
||||
while (idx < cnt) {
|
||||
eLand n = tab[idx];
|
||||
if (incompatible(n, old) || !isLandIngame(n))
|
||||
tab[idx] = tab[--cnt];
|
||||
else
|
||||
idx++;
|
||||
}
|
||||
|
||||
|
||||
if (!cnt) {
|
||||
addMessage("No eligible land candidates!");
|
||||
return old;
|
||||
}
|
||||
|
||||
eLand n = tab[hrand(cnt)];
|
||||
if (weirdhyperbolic && specialland == laCrossroads4 && isCrossroads(n))
|
||||
n = laCrossroads4;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
|
@ -711,14 +772,26 @@ EX eLand getLandForList(cell *c) {
|
|||
return l;
|
||||
}
|
||||
|
||||
EX bool use_custom_land_list;
|
||||
EX array<bool, landtypes> custom_land_list;
|
||||
EX array<int, landtypes> custom_land_treasure;
|
||||
EX array<int, landtypes> custom_land_difficulty;
|
||||
EX array<int, landtypes> custom_land_wandering;
|
||||
|
||||
EX bool isLandIngame(eLand l) {
|
||||
if(isElemental(l)) l = laElementalWall;
|
||||
if(use_custom_land_list) return custom_land_list[l];
|
||||
if(dual::state == 2 && !dual::check_side(l)) return false;
|
||||
if((eubinary || sol) && isCyclic(l) && l != specialland) return false;
|
||||
if(l == laCamelot && hyperbolic && WDIM == 3) return false;
|
||||
return land_validity(l).flags & lv::appears_in_full;
|
||||
}
|
||||
|
||||
EX bool landUnlockedIngame(eLand l) {
|
||||
if(!peace::on && !landUnlocked(l)) return false;
|
||||
return isLandIngame(l);
|
||||
}
|
||||
|
||||
namespace lv {
|
||||
|
||||
flagtype q0 = lv::display_error_message | lv::display_in_help | lv::appears_in_geom_exp;
|
||||
|
@ -744,6 +817,7 @@ namespace lv {
|
|||
land_validity_t out_of_theme = { 3, qm2 &~ lv::appears_in_full, "Out of theme for the full game."};
|
||||
land_validity_t no_game = { 2, q2 &~ lv::appears_in_full, "No game here."};
|
||||
land_validity_t not_in_chaos = { 0, q0, "Does not work in chaos mode."};
|
||||
land_validity_t not_in_landscape = { 0, q0, "Does not work in landscape mode."};
|
||||
land_validity_t not_in_full_game = {2, qm2 &~ lv::appears_in_full, "Not in the full game."};
|
||||
land_validity_t not_in_full_game3 = {3, qm2 &~ lv::appears_in_full, "Not in the full game."};
|
||||
land_validity_t special_chaos = { 2, qm2, "Special construction in the Chaos mode." };
|
||||
|
@ -801,6 +875,132 @@ EX const int cursed_when = 386;
|
|||
|
||||
EX const int walls_when = 388;
|
||||
|
||||
EX void mark_tamper() { cheater++; }
|
||||
|
||||
EX void customize_land_in_list(eLand l) {
|
||||
cmode = sm::SIDE | sm::MAYDARK; gamescreen();
|
||||
|
||||
dialog::init(XLATN(linf[l].name), linf[l].color);
|
||||
|
||||
help = generateHelpForLand(l);
|
||||
addHelpWithTitle();
|
||||
|
||||
dialog::addBreak(100);
|
||||
|
||||
dialog::addBoolItem(XLAT("land in game"), custom_land_list[l], 'a');
|
||||
dialog::add_action([l] {
|
||||
custom_land_list[l] = !custom_land_list[l];
|
||||
cheater++;
|
||||
});
|
||||
|
||||
dialog::addSelItem(XLAT("treasure rate"), its(custom_land_treasure[l]), 't');
|
||||
dialog::add_action([l] {
|
||||
dialog::editNumber(custom_land_treasure[l], 0, 1000, 10, 100, XLAT("treasure rate in %the1", linf[l].name), "");
|
||||
dialog::get_ne().reaction = mark_tamper;
|
||||
});
|
||||
|
||||
dialog::addSelItem(XLAT("difficulty"), its(custom_land_difficulty[l]), 'd');
|
||||
dialog::add_action([l] {
|
||||
dialog::editNumber(custom_land_difficulty[l], 0, 1000, 10, 100, XLAT("difficulty of %the1", linf[l].name), "");
|
||||
dialog::get_ne().reaction = mark_tamper;
|
||||
});
|
||||
|
||||
dialog::addSelItem(XLAT("wandering"), its(custom_land_wandering[l]), 'w');
|
||||
dialog::add_action([l] {
|
||||
dialog::editNumber(custom_land_wandering[l], 0, 1000, 10, 100, XLAT("difficulty of %the1", linf[l].name), "");
|
||||
dialog::get_ne().reaction = mark_tamper;
|
||||
});
|
||||
|
||||
gen_landvisited();
|
||||
if(landvisited[l]) {
|
||||
dialog::addItem(XLAT("test"), 'T');
|
||||
dialog::add_action([l] {
|
||||
stop_game(); firstland = specialland = l; start_game();
|
||||
});
|
||||
}
|
||||
|
||||
dialog::addBack();
|
||||
dialog::display();
|
||||
}
|
||||
|
||||
EX void customize_land_list() {
|
||||
cmode = sm::SIDE | sm::MAYDARK; gamescreen();
|
||||
dialog::init(XLAT("custom land list"));
|
||||
if(dialog::infix != "") mouseovers = dialog::infix;
|
||||
|
||||
generateLandList([] (eLand l) {
|
||||
if(!use_custom_land_list) {
|
||||
custom_land_list[l] = isLandIngame(l);
|
||||
custom_land_treasure[l] = 100;
|
||||
custom_land_difficulty[l] = 100;
|
||||
custom_land_wandering[l] = 100;
|
||||
}
|
||||
if(dialog::infix != "" && !dialog::hasInfix(linf[l].name)) return false;
|
||||
if(l == laCanvas) return true;
|
||||
return !!(land_validity(l).flags & lv::appears_in_geom_exp);
|
||||
});
|
||||
stable_sort(landlist.begin(), landlist.end(), [] (eLand l1, eLand l2) { return land_validity(l1).quality_level > land_validity(l2).quality_level; });
|
||||
|
||||
dialog::start_list(900, 900, '1');
|
||||
for(eLand l: landlist) {
|
||||
dialog::addBoolItem(XLAT1(linf[l].name), custom_land_list[l], dialog::list_fake_key++);
|
||||
string s;
|
||||
if(custom_land_treasure[l] != 100) s += "$" + its(custom_land_treasure[l]) + " ";
|
||||
if(custom_land_difficulty[l] != 100) s += "!" + its(custom_land_difficulty[l]) + " ";
|
||||
if(custom_land_wandering[l] != 100) s += "^" + its(custom_land_wandering[l]) + " ";
|
||||
if(s != "") dialog::lastItem().value = s;
|
||||
dialog::add_action_confirmed([l] {
|
||||
if(!use_custom_land_list) {
|
||||
stop_game();
|
||||
use_custom_land_list = true;
|
||||
start_game();
|
||||
}
|
||||
pushScreen([l] { customize_land_in_list(l); });
|
||||
});
|
||||
}
|
||||
dialog::end_list();
|
||||
|
||||
dialog::addInfo(XLAT("press letters to search"));
|
||||
dialog::addBoolItem("custom land list mode", use_custom_land_list, 'U');
|
||||
dialog::add_action_confirmed([] {
|
||||
stop_game();
|
||||
use_custom_land_list = !use_custom_land_list;
|
||||
start_game();
|
||||
});
|
||||
|
||||
if(use_custom_land_list) {
|
||||
dialog::addItem("disable/enable all", 'D');
|
||||
dialog::add_action([] {
|
||||
int qty = 0;
|
||||
for(int i=0; i<landtypes; i++) if(custom_land_list[i]) qty++;
|
||||
for(int i=0; i<landtypes; i++) custom_land_list[i] = !qty;
|
||||
});
|
||||
}
|
||||
else dialog::addBreak(100);
|
||||
|
||||
dialog::addHelp();
|
||||
dialog::add_action([] {
|
||||
gotoHelp(XLAT(
|
||||
"In this mode, you can choose the lands you want to be in game. You can also customize their treasure rate and difficulty.\n\n"
|
||||
"While the game automatically selects a list of lands by default, "
|
||||
"based on whether it thinks they work well in the currently selected tiling, "
|
||||
"you might not agree with this selection.\n\n"
|
||||
"Note that, often, lands are enabled or disabled for a GOOD reason! Use at your own risk.\n\n"
|
||||
"Just click on a land to configure it. If you are not in the custom land list mode, "
|
||||
"this will restart the game. You can change the settings during a custom game, but it counts as a cheat."
|
||||
));
|
||||
});
|
||||
dialog::addBack();
|
||||
dialog::display();
|
||||
|
||||
keyhandler = [] (int sym, int uni) {
|
||||
dialog::handleNavigation(sym, uni);
|
||||
|
||||
if(dialog::editInfix(uni)) dialog::list_skip = 0;
|
||||
else if(doexiton(sym, uni)) popScreen();
|
||||
};
|
||||
}
|
||||
|
||||
// check if the given land should appear in lists
|
||||
EX land_validity_t& land_validity(eLand l) {
|
||||
|
||||
|
@ -994,7 +1194,7 @@ EX land_validity_t& land_validity(eLand l) {
|
|||
if(l == laWhirlwind && hyperbolic_not37)
|
||||
return pattern_incompatibility;
|
||||
|
||||
bool better_mirror = !geometry && STDVAR && !ls::hv_structure();
|
||||
bool better_mirror = !geometry && STDVAR && !ls::hv_structure() && !among(land_structure, lsTotalChaos, lsPatchedChaos, lsLandscape, lsVineWalls);
|
||||
|
||||
// available only in non-standard geometries
|
||||
if(l == laMirrorOld && better_mirror)
|
||||
|
@ -1015,6 +1215,9 @@ EX land_validity_t& land_validity(eLand l) {
|
|||
if(l == laHaunted && ls::std_chaos())
|
||||
return not_in_chaos;
|
||||
|
||||
if(among(l, laHaunted, laElementalWall) && land_structure == lsLandscape)
|
||||
return not_in_landscape;
|
||||
|
||||
// standard, non-PTM specific
|
||||
if(l == laCrossroads5 && old_daily_id < 999 && tactic::on)
|
||||
return not_in_ptm;
|
||||
|
|
|
@ -206,6 +206,7 @@ EX modecode_t legacy_modecode() {
|
|||
if(int(geometry) > 3 || int(variation) > 1) return UNKNOWN;
|
||||
if(casual) return UNKNOWN;
|
||||
if(bow::weapon) return UNKNOWN;
|
||||
if(use_custom_land_list) return UNKNOWN;
|
||||
|
||||
bool is_default_land_structure =
|
||||
(princess::challenge || tactic::on) ? ls::single() :
|
||||
|
|
|
@ -213,7 +213,7 @@ template<class T> struct walker {
|
|||
int spin;
|
||||
/** \brief are we mirrored */
|
||||
bool mirrored;
|
||||
walker<T> (T *at = NULL, int s = 0, bool m = false) : at(at), spin(s), mirrored(m) { if(at) s = at->c.fix(s); }
|
||||
walker(T *at = NULL, int s = 0, bool m = false) : at(at), spin(s), mirrored(m) { if(at) s = at->c.fix(s); }
|
||||
/** \brief spin by i to the left (or right, when mirrored */
|
||||
walker<T>& operator += (int i) {
|
||||
spin = at->c.fix(spin+(mirrored?-i:i));
|
||||
|
|
|
@ -491,6 +491,9 @@ EX namespace mapstream {
|
|||
f.write(gp::param.second);
|
||||
}
|
||||
#endif
|
||||
#if CAP_IRR
|
||||
if(IRREGULAR) irr::save_map_bin(f);
|
||||
#endif
|
||||
#if MAXMDIM >= 4
|
||||
if(variation == eVariation::coxeter) {
|
||||
f.write(reg3::coxeter_param);
|
||||
|
@ -587,6 +590,9 @@ EX namespace mapstream {
|
|||
f.read(gp::param.second);
|
||||
}
|
||||
#endif
|
||||
#if CAP_IRR
|
||||
if(IRREGULAR) { irr::load_map_full(f); stop_game(); }
|
||||
#endif
|
||||
#if MAXMDIM >= 4
|
||||
if(variation == eVariation::coxeter && vernum >= 0xA908) {
|
||||
f.read(reg3::coxeter_param);
|
||||
|
@ -740,14 +746,16 @@ EX namespace mapstream {
|
|||
f.write(gen_wandering);
|
||||
f.write(reptilecheat);
|
||||
f.write(timerghost);
|
||||
f.write(patterns::canvasback);
|
||||
f.write(ccolor::plain.ctab[0]);
|
||||
f.write(patterns::whichShape);
|
||||
f.write(patterns::subpattern_flags);
|
||||
f.write(patterns::whichCanvas);
|
||||
char wc = '*';
|
||||
f.write(wc);
|
||||
f.write(ccolor::which->name);
|
||||
f.write(patterns::displaycodes);
|
||||
f.write(canvas_default_wall);
|
||||
f.write(mapeditor::drawplayer);
|
||||
if(patterns::whichCanvas == 'f') f.write(patterns::color_formula);
|
||||
if(ccolor::which == &ccolor::formula) f.write(ccolor::color_formula);
|
||||
f.write(canvasfloor);
|
||||
f.write(canvasdark);
|
||||
|
||||
|
@ -940,15 +948,21 @@ EX namespace mapstream {
|
|||
f.read(gen_wandering);
|
||||
f.read(reptilecheat);
|
||||
f.read(timerghost);
|
||||
f.read(patterns::canvasback);
|
||||
f.read(ccolor::plain.ctab[0]);
|
||||
f.read(patterns::whichShape);
|
||||
f.read(patterns::subpattern_flags);
|
||||
f.read(patterns::whichCanvas);
|
||||
char wc;
|
||||
f.read(wc);
|
||||
if(wc == '*') {
|
||||
string name;
|
||||
f.read(name);
|
||||
for(auto& p: ccolor::all) if(p->name == name) ccolor::which = p;
|
||||
}
|
||||
f.read(patterns::displaycodes);
|
||||
if(f.vernum >= 0xA816)
|
||||
f.read(canvas_default_wall);
|
||||
f.read(mapeditor::drawplayer);
|
||||
if(patterns::whichCanvas == 'f') f.read(patterns::color_formula);
|
||||
if(wc == 'f') f.read(ccolor::color_formula);
|
||||
if(f.vernum >= 0xA90D) {
|
||||
f.read(canvasfloor);
|
||||
f.read(canvasdark);
|
||||
|
@ -2588,16 +2602,16 @@ EX namespace mapeditor {
|
|||
bool onelayeronly;
|
||||
|
||||
bool loadPicFile(const string& s) {
|
||||
fhstream f(picfile, "rt");
|
||||
fhstream f(s, "rt");
|
||||
if(!f.f) {
|
||||
addMessage(XLAT("Failed to load pictures from %1", picfile));
|
||||
addMessage(XLAT("Failed to load pictures from %1", s));
|
||||
return false;
|
||||
}
|
||||
scanline(f);
|
||||
scan(f, f.vernum);
|
||||
printf("vernum = %x\n", f.vernum);
|
||||
if(f.vernum == 0) {
|
||||
addMessage(XLAT("Failed to load pictures from %1", picfile));
|
||||
addMessage(XLAT("Failed to load pictures from %1", s));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -2625,6 +2639,7 @@ EX namespace mapeditor {
|
|||
}
|
||||
|
||||
initShape(i, j);
|
||||
println(hlog, "shape ", tie(i, j), " layer ", l);
|
||||
usershapelayer& ds(usershapes[i][j]->d[l]);
|
||||
if(f.vernum >= 0xA608) scan(f, ds.zlevel);
|
||||
ds.shift = readHyperpoint(f);
|
||||
|
@ -2738,8 +2753,7 @@ EX namespace mapeditor {
|
|||
stop_game();
|
||||
enable_canvas();
|
||||
canvas_default_wall = waInvisibleFloor;
|
||||
patterns::whichCanvas = 'g';
|
||||
patterns::canvasback = 0xFFFFFF;
|
||||
ccolor::set_plain(0xFFFFFF);
|
||||
dtcolor = (forecolor << 8) | 255;
|
||||
drawplayer = false;
|
||||
vid.use_smart_range = 2;
|
||||
|
|
|
@ -575,6 +575,7 @@ EX bool destroyHalfvine(cell *c, eWall newwall IS(waNone), int tval IS(6)) {
|
|||
}
|
||||
|
||||
EX int coastvalEdge(cell *c) { return coastval(c, laIvoryTower); }
|
||||
EX int coastvalWest(cell *c) { return coastval(c, laWestWall); }
|
||||
|
||||
EX int gravityLevel(cell *c) {
|
||||
if(c->land == laIvoryTower && ls::hv_structure())
|
||||
|
@ -601,10 +602,10 @@ EX int gravityLevelDiff(cell *c, cell *d) {
|
|||
if(shmup::on) return 0;
|
||||
|
||||
int nid = neighborId(c, d);
|
||||
int id1 = parent_id(c, 1, coastvalEdge) + 1;
|
||||
int id1 = parent_id(c, 1, coastvalWest) + 1;
|
||||
int di1 = angledist(c->type, id1, nid);
|
||||
|
||||
int id2 = parent_id(c, -1, coastvalEdge) - 1;
|
||||
int id2 = parent_id(c, -1, coastvalWest) - 1;
|
||||
int di2 = angledist(c->type, id2, nid);
|
||||
|
||||
if(di1 < di2) return 1;
|
||||
|
@ -708,8 +709,8 @@ EX void checkTide(cell *c) {
|
|||
if(!c2) continue;
|
||||
if(c2->land == laBarrier || c2->land == laOceanWall) ;
|
||||
else if(c2->land == laOcean)
|
||||
seadist = min(seadist, c2->SEADIST ? c2->SEADIST+1 : 7),
|
||||
landdist = min(landdist, c2->LANDDIST ? c2->LANDDIST+1 : 7);
|
||||
seadist = min(seadist, c2->SEADIST >= 1 ? c2->SEADIST+1 : 7),
|
||||
landdist = min(landdist, c2->LANDDIST >= 1 ? c2->LANDDIST+1 : 7);
|
||||
else if(isSealand(c2->land)) seadist = 1;
|
||||
else landdist = 1;
|
||||
}
|
||||
|
@ -745,18 +746,27 @@ EX void checkTide(cell *c) {
|
|||
#endif
|
||||
}
|
||||
|
||||
EX bool makeEmpty(cell *c) {
|
||||
EX bool makeNoMonster(cell *c) {
|
||||
changes.ccell(c);
|
||||
if(isAnyIvy(c->monst)) killMonster(c, moPlayer, 0);
|
||||
else if(c->monst == moPair) {
|
||||
changes.ccell(c->move(c->mondir));
|
||||
if(c->move(c->mondir)->monst == moPair)
|
||||
c->move(c->mondir)->monst = moNone;
|
||||
}
|
||||
else if(isWorm(c->monst)) {
|
||||
if(!items[itOrbDomination]) return false;
|
||||
}
|
||||
else if(isMultitile(c->monst)) {
|
||||
return false;
|
||||
}
|
||||
else c->monst = moNone;
|
||||
return true;
|
||||
}
|
||||
|
||||
EX bool makeEmpty(cell *c) {
|
||||
if(c->monst != moPrincess) {
|
||||
if(isAnyIvy(c->monst)) killMonster(c, moPlayer, 0);
|
||||
else if(c->monst == moPair) {
|
||||
if(c->move(c->mondir)->monst == moPair)
|
||||
c->move(c->mondir)->monst = moNone;
|
||||
}
|
||||
else if(isWorm(c->monst)) {
|
||||
if(!items[itOrbDomination]) return false;
|
||||
}
|
||||
else c->monst = moNone;
|
||||
if(!makeNoMonster(c)) return false;
|
||||
}
|
||||
|
||||
if(c->land == laCanvas) ;
|
||||
|
@ -814,10 +824,12 @@ EX bool makeEmpty(cell *c) {
|
|||
}
|
||||
|
||||
if(c->land == laWildWest) {
|
||||
forCellEx(c2, c)
|
||||
forCellEx(c3, c2)
|
||||
if(c3->wall != waBarrier)
|
||||
c3->wall = waNone;
|
||||
celllister cl(cwt.at, 100, 1000000, NULL);
|
||||
for(cell *c: cl.lst) {
|
||||
if(c == cwt.at) continue;
|
||||
if(c->wall != waSaloon) break;
|
||||
c->wall = waNone;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
69
menus.cpp
69
menus.cpp
|
@ -374,6 +374,9 @@ EX void showCreative() {
|
|||
}
|
||||
#endif
|
||||
|
||||
dialog::addItem(XLAT("line patterns"), 'l');
|
||||
dialog::add_action_push(linepatterns::showMenu);
|
||||
|
||||
// dialog::addBoolItem(XLAT("expansion"), viewdists, 'x');
|
||||
|
||||
dialog::addBreak(50);
|
||||
|
@ -464,12 +467,69 @@ EX void show_chaos() {
|
|||
add_edit(horodisk_from);
|
||||
else if(land_structure == lsChaosRW)
|
||||
add_edit(randomwalk_size);
|
||||
else if(land_structure == lsLandscape)
|
||||
add_edit(landscape_div);
|
||||
else if(land_structure == lsCursedWalls)
|
||||
add_edit(curse_percentage);
|
||||
else
|
||||
dialog::addBreak(100);
|
||||
dialog::addBack();
|
||||
dialog::display();
|
||||
}
|
||||
|
||||
EX string custom_welcome;
|
||||
|
||||
string customfile = "custom.hrm";
|
||||
|
||||
EX void show_custom() {
|
||||
cmode = sm::SIDE | sm::MAYDARK;
|
||||
gamescreen();
|
||||
dialog::init(XLAT("custom mode"));
|
||||
|
||||
if(custom_welcome != "") {
|
||||
dialog::addInfo("custom welcome message:");
|
||||
dialog::addInfo(custom_welcome);
|
||||
dialog::addItem("edit", '/');
|
||||
}
|
||||
else {
|
||||
dialog::addItem("custom welcome message", '/');
|
||||
}
|
||||
dialog::add_action([] () {
|
||||
dialog::edit_string(custom_welcome, "custom welcome message", "");
|
||||
});
|
||||
dialog::addBreak(100);
|
||||
dialog::addItem("save custom mode", 's');
|
||||
dialog::add_action([] {
|
||||
dialog::openFileDialog(customfile, XLAT("file to save:"), ".hrm", [] () {
|
||||
try {
|
||||
save_mode_to_file(customfile);
|
||||
addMessage(XLAT("Mode saved to %1", customfile));
|
||||
return true;
|
||||
}
|
||||
catch(hstream_exception& e) {
|
||||
addMessage(XLAT("Failed to save mode to %1", customfile));
|
||||
return false;
|
||||
}
|
||||
});
|
||||
});
|
||||
dialog::addItem("load custom mode", 'l');
|
||||
dialog::add_action([] {
|
||||
dialog::openFileDialog(customfile, XLAT("file to load:"), ".hrm", [] () {
|
||||
try {
|
||||
load_mode_from_file(customfile);
|
||||
addMessage(XLAT("Loaded mode from %1", customfile));
|
||||
return true;
|
||||
}
|
||||
catch(hstream_exception& e) {
|
||||
addMessage(XLAT("Failed to load mode from %1", customfile));
|
||||
return false;
|
||||
}
|
||||
});
|
||||
});
|
||||
dialog::addBack();
|
||||
dialog::display();
|
||||
}
|
||||
|
||||
EX void mode_higlights() {
|
||||
cmode = sm::NOSCR;
|
||||
gamescreen();
|
||||
|
@ -685,6 +745,9 @@ EX void showChangeMode() {
|
|||
multi::cpid = 0;
|
||||
menuitem_land_structure('l');
|
||||
|
||||
dialog::addBoolItem(XLAT("custom land list"), use_custom_land_list, 'L');
|
||||
dialog::add_action_push(customize_land_list);
|
||||
|
||||
dialog::addBoolItem(XLAT("weapon selection"), bow::weapon, 'b');
|
||||
dialog::add_action_push(bow::showMenu);
|
||||
|
||||
|
@ -722,7 +785,7 @@ EX void showChangeMode() {
|
|||
#endif
|
||||
dialog::addBoolItem(XLAT("%1 Challenge", moPrincess), (princess::challenge), 'P');
|
||||
dialog::add_action_confirmed([] {
|
||||
if(!princess::everSaved)
|
||||
if(!princess::everSaved && !autocheat)
|
||||
addMessage(XLAT("Save %the1 first to unlock this challenge!", moPrincess));
|
||||
else restart_game(rg::princess);
|
||||
});
|
||||
|
@ -746,6 +809,8 @@ EX void showChangeMode() {
|
|||
dialog::addBreak(50);
|
||||
dialog::addItem(XLAT("highlights & achievements"), 'h');
|
||||
dialog::add_action_push(mode_higlights);
|
||||
dialog::addItem(XLAT("custom mode manager"), 'm');
|
||||
dialog::add_action_push(show_custom);
|
||||
|
||||
dialog::addBack();
|
||||
dialog::display();
|
||||
|
@ -947,7 +1012,7 @@ EX void showStartMenu() {
|
|||
stop_game();
|
||||
enable_canvas();
|
||||
cheater = true;
|
||||
patterns::canvasback = 0xFFFFFF;
|
||||
ccolor::set_plain(0xFFFFFF);
|
||||
mapeditor::drawplayer = false;
|
||||
start_game();
|
||||
clearMessages();
|
||||
|
|
12
models.cpp
12
models.cpp
|
@ -139,6 +139,7 @@ projection_configuration::projection_configuration() {
|
|||
ptr_ball = new transmatrix;
|
||||
*ptr_ball = cspin(1, 2, 20._deg);
|
||||
ptr_camera = new transmatrix; *ptr_camera = Id;
|
||||
offside = 0; offside2 = M_PI;
|
||||
}
|
||||
|
||||
EX namespace models {
|
||||
|
@ -643,6 +644,11 @@ EX namespace models {
|
|||
if(among(vpmodel, mdLoximuthal, mdRetroHammer, mdRetroCraig))
|
||||
add_edit(vpconf.loximuthal_parameter);
|
||||
|
||||
if(among(vpmodel, mdPolar)) {
|
||||
add_edit(vpconf.offside);
|
||||
add_edit(vpconf.offside2);
|
||||
}
|
||||
|
||||
if(among(vpmodel, mdAitoff, mdHammer, mdWinkelTripel))
|
||||
add_edit(vpconf.aitoff_parameter);
|
||||
|
||||
|
@ -1009,6 +1015,12 @@ EX namespace models {
|
|||
"The Aitoff projection is obtained by multiplying the longitude by 1/2, using azimuthal equidistant projection, and then dividing X by 1/2. "
|
||||
"Hammer projection is similar but equi-area projection is used instead. "
|
||||
"Here you can change this parameter.", 'b');
|
||||
param_f(p.offside, sp+"offside")
|
||||
-> editable(0, TAU, TAU/10, "offside parameter",
|
||||
"Do not center the projection on the player -- move the center offside. Useful in polar, where the value equal to offside2 can be used to center the projection on the player.", 'o');
|
||||
param_f(p.offside2, sp+"offside2")
|
||||
-> editable(0, TAU, TAU/10, "offside parameter II",
|
||||
"In polar projection, what distance to display in the center. Use asinh(1) (in hyperbolic) to make it conformal in the center, and pi to have the projection extend the same distance to the left, right, and upwards.", 'O');
|
||||
param_f(p.miller_parameter, sp+"miller");
|
||||
param_f(p.loximuthal_parameter, sp+"loximuthal")
|
||||
-> editable(-90._deg, 90._deg, .1, "loximuthal parameter",
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#include "hyper.h"
|
||||
namespace hr {
|
||||
|
||||
EX int avengers, mirrorspirits, wandering_jiangshi, jiangshi_on_screen;
|
||||
EX int avengers, mirrorspirits, wandering_jiangshi, jiangshi_on_screen, splitrocks;
|
||||
|
||||
EX bool timerghost = true;
|
||||
EX bool gen_wandering = true;
|
||||
|
@ -192,7 +192,7 @@ EX int reptilemax() {
|
|||
return r;
|
||||
}
|
||||
|
||||
bool wchance(int a, int of, int reduction = 0) {
|
||||
bool wchance_in(eLand l, int a, int of, int reduction = 0) {
|
||||
of *= 10;
|
||||
a += yendor::hardness() + 1;
|
||||
if(isCrossroads(cwt.at->land))
|
||||
|
@ -206,6 +206,11 @@ bool wchance(int a, int of, int reduction = 0) {
|
|||
a -= reduction;
|
||||
if(a < 0) return false;
|
||||
|
||||
if(use_custom_land_list) {
|
||||
of *= 100;
|
||||
a *= custom_land_wandering[l];
|
||||
}
|
||||
|
||||
return hrand(a+of) < a;
|
||||
}
|
||||
|
||||
|
@ -337,7 +342,7 @@ EX void wandering() {
|
|||
if(closed_or_bounded && specialland == laClearing)
|
||||
clearing::new_root();
|
||||
|
||||
if(cwt.at->land == laZebra && cwt.at->wall == waNone && wchance(items[itZebra], 20))
|
||||
if(cwt.at->land == laZebra && cwt.at->wall == waNone && wchance_in(laZebra, items[itZebra], 20))
|
||||
wanderingZebra(cwt.at);
|
||||
|
||||
bool smallbounded_generation = smallbounded || (closed_manifold && specialland == laClearing);
|
||||
|
@ -370,6 +375,8 @@ EX void wandering() {
|
|||
cell *c = dcal[i];
|
||||
if(!valid(c)) continue;
|
||||
if(isPlayerOn(c)) break;
|
||||
|
||||
auto wchance = [c] (int a, int of, int reduction = 0) { return wchance_in(c->land, a, of, reduction); };
|
||||
|
||||
if(specialland == laStorms) {
|
||||
// place the sandstone wall completely randomly (but not on the player)
|
||||
|
@ -555,6 +562,12 @@ EX void wandering() {
|
|||
|
||||
else if(c->monst || c->pathdist == PINFD) break;
|
||||
|
||||
else if(c->land == laAsteroids && splitrocks && canReachPlayer(c, moYeti)) {
|
||||
c->monst = moAsteroid;
|
||||
splitrocks--;
|
||||
continue;
|
||||
}
|
||||
|
||||
else if(c->land == laAsteroids) {
|
||||
int gen = 0;
|
||||
if(asteroids_generated * 12 <= items[itAsteroid]) gen = 2;
|
||||
|
|
27
multi.cpp
27
multi.cpp
|
@ -11,13 +11,14 @@ namespace hr {
|
|||
EX namespace multi {
|
||||
|
||||
#if HDR
|
||||
static constexpr int SCANCODES = 512;
|
||||
static constexpr int MAXJOY = 8;
|
||||
static constexpr int MAXBUTTON = 64;
|
||||
static constexpr int MAXAXE = 16;
|
||||
static constexpr int MAXHAT = 4;
|
||||
|
||||
struct config {
|
||||
char keyaction[512];
|
||||
char keyaction[SCANCODES];
|
||||
char joyaction[MAXJOY][MAXBUTTON];
|
||||
char axeaction[MAXJOY][MAXAXE];
|
||||
char hataction[MAXJOY][MAXHAT][4];
|
||||
|
@ -171,7 +172,7 @@ int* dzconfigs[24];
|
|||
string listkeys(config& scfg, int id) {
|
||||
#if CAP_SDL
|
||||
string lk = "";
|
||||
for(int i=0; i<512; i++)
|
||||
for(int i=0; i<SCANCODES; i++)
|
||||
if(scfg.keyaction[i] == id)
|
||||
#if CAP_SDL2
|
||||
lk = lk + " " + SDL_GetScancodeName(SDL_Scancode(i));
|
||||
|
@ -265,7 +266,8 @@ struct key_configurer {
|
|||
if(!setwhat) dialog::handleNavigation(sym, uni);
|
||||
if(sym) {
|
||||
if(setwhat) {
|
||||
which_config->keyaction[sym] = setwhat;
|
||||
int scan = key_to_scan(sym);
|
||||
if(scan >= 0 && scan < SCANCODES) which_config->keyaction[scan] = setwhat;
|
||||
setwhat = 0;
|
||||
}
|
||||
else if(uni >= 'a' && uni < 'a' + isize(shmupcmdtable) && shmupcmdtable[uni-'a'][0])
|
||||
|
@ -584,9 +586,19 @@ void pressaction(int id) {
|
|||
actionspressed[id]++;
|
||||
}
|
||||
|
||||
EX int key_to_scan(int sym) {
|
||||
#if CAP_SDL2
|
||||
return SDL_GetScancodeFromKey(sym);
|
||||
#else
|
||||
return sym;
|
||||
#endif
|
||||
}
|
||||
|
||||
EX bool notremapped(int sym) {
|
||||
auto& scfg = scfg_default;
|
||||
int k = scfg.keyaction[sym];
|
||||
int sc = key_to_scan(sym);
|
||||
if(sc < 0 || sc >= SCANCODES) return true;
|
||||
int k = scfg.keyaction[sc];
|
||||
if(k == 0) return true;
|
||||
k /= 16;
|
||||
if(k > 3) k--; else if(k==3) k = 0;
|
||||
|
@ -595,7 +607,7 @@ EX bool notremapped(int sym) {
|
|||
|
||||
EX void sconfig_savers(config& scfg, string prefix) {
|
||||
// unfortunately we cannot use key names here because SDL is not yet initialized
|
||||
for(int i=0; i<512; i++)
|
||||
for(int i=0; i<SCANCODES; i++)
|
||||
addsaver(scfg.keyaction[i], prefix + string("key:")+its(i));
|
||||
|
||||
for(int i=0; i<MAXJOY; i++) {
|
||||
|
@ -613,7 +625,7 @@ EX void sconfig_savers(config& scfg, string prefix) {
|
|||
}
|
||||
|
||||
EX void clear_config(config& scfg) {
|
||||
for(int i=0; i<512; i++) scfg.keyaction[i] = 0;
|
||||
for(int i=0; i<SCANCODES; i++) scfg.keyaction[i] = 0;
|
||||
}
|
||||
|
||||
EX void initConfig() {
|
||||
|
@ -821,7 +833,8 @@ EX void handleInput(int delta, config &scfg) {
|
|||
get_actions(scfg);
|
||||
|
||||
const Uint8 *keystate = SDL12_GetKeyState(NULL);
|
||||
if(keystate[SDLK_LCTRL] || keystate[SDLK_RCTRL]) d /= 5;
|
||||
|
||||
if(keystate[SDL12(SDLK_LCTRL, SDL_SCANCODE_LCTRL)] || keystate[SDL12(SDLK_RCTRL, SDL_SCANCODE_RCTRL)]) d /= 5;
|
||||
|
||||
double panx =
|
||||
actionspressed[49] - actionspressed[51] + axespressed[2] / 32000.0;
|
||||
|
|
|
@ -29,7 +29,7 @@ struct gamedata {
|
|||
::new (&record[index]) T(std::move(x));
|
||||
}
|
||||
else {
|
||||
T& at = (T&) record[index];
|
||||
T& at = *((T*) (void*) &(record[index]));
|
||||
x = std::move(at);
|
||||
at.~T();
|
||||
}
|
||||
|
@ -78,7 +78,7 @@ void gamedata_all(gamedata& gd) {
|
|||
gd.store(genrange_bonus);
|
||||
gd.store(gamerange_bonus);
|
||||
gd.store(targets);
|
||||
gd.store(patterns::rwalls);
|
||||
gd.store(ccolor::rwalls);
|
||||
if(GOLDBERG) gd.store(gp::param);
|
||||
callhooks(hooks_gamedata, &gd);
|
||||
}
|
||||
|
|
|
@ -1360,6 +1360,7 @@ EX namespace hybrid {
|
|||
cell* gamestart() override { return getCell(underlying_map->gamestart(), 0); }
|
||||
|
||||
hrmap_hybrid() {
|
||||
underlying_map = nullptr;
|
||||
twisted = false;
|
||||
disc_quotient = 0;
|
||||
in_underlying([this] { initcells(); underlying_map = currentmap; });
|
||||
|
@ -2358,7 +2359,7 @@ EX namespace rots {
|
|||
ptds.clear();
|
||||
drawthemap();
|
||||
drawqueue();
|
||||
displaychr(current_display->xcenter, current_display->ycenter, 0, 24, '+', 0xFFFFFFFF);
|
||||
displaychr(current_display->xcenter, current_display->ycenter, 0, 24 * mapfontscale / 100, '+', 0xFFFFFFFF);
|
||||
glflush();
|
||||
});
|
||||
gmatrix = std::move(g);
|
||||
|
|
37
orbs.cpp
37
orbs.cpp
|
@ -664,7 +664,7 @@ EX void teleportTo(cell *dest) {
|
|||
}
|
||||
|
||||
/* calls changes.rollback or changes.commit */
|
||||
EX bool jumpTo(orbAction a, cell *dest, eItem byWhat, int bonuskill IS(0), eMonster dashmon IS(moNone)) {
|
||||
EX bool jumpTo(orbAction a, cell *dest, eItem byWhat, int bonuskill IS(0), eMonster dashmon IS(moNone), cell *phasecell IS(nullptr)) {
|
||||
if(byWhat != itStrongWind) playSound(dest, "orb-frog");
|
||||
cell *from = cwt.at;
|
||||
changes.value_keep(cwt);
|
||||
|
@ -683,7 +683,10 @@ EX bool jumpTo(orbAction a, cell *dest, eItem byWhat, int bonuskill IS(0), eMons
|
|||
|
||||
if(byWhat == itOrbPhasing) {
|
||||
useupOrb(itOrbPhasing, 5);
|
||||
addMessage(XLAT("You jump!"));
|
||||
if(phasecell->monst)
|
||||
addMessage(XLAT("You phase through %the1!", phasecell->monst));
|
||||
else
|
||||
addMessage(XLAT("You phase through %the1!", phasecell->wall));
|
||||
}
|
||||
|
||||
movecost(from, dest, 1);
|
||||
|
@ -822,7 +825,14 @@ void telekinesis(cell *dest) {
|
|||
}
|
||||
|
||||
moveItem(dest, cwt.at, true);
|
||||
eItem it = cwt.at->item;
|
||||
bool saf = it == itOrbSafety;
|
||||
collectItem(cwt.at, cwt.at, true);
|
||||
if(cwt.at->item == it)
|
||||
animateMovement(match(dest, cwt.at), LAYER_BOAT);
|
||||
else if(!saf)
|
||||
animate_item_throw(dest, cwt.at, it);
|
||||
|
||||
useupOrb(itOrbSpace, cost.first);
|
||||
if(cost.second)
|
||||
markOrb(itOrbMagnetism);
|
||||
|
@ -874,6 +884,10 @@ EX eMonster summonedAt(cell *dest) {
|
|||
dest->land == laWarpCoast ? moRatling :
|
||||
dest->land == laDocks ? moWaterElemental :
|
||||
moPirate;
|
||||
if(among(dest->wall, waDeepWater, waShallow))
|
||||
return moRusalka;
|
||||
if(dest->wall == waCamelotMoat)
|
||||
return moWaterElemental;
|
||||
if(isReptile(dest->wall))
|
||||
return moReptile;
|
||||
if(dest->wall == waChasm)
|
||||
|
@ -1136,8 +1150,10 @@ void blowoff(const movei& mi) {
|
|||
auto& ct = mi.t;
|
||||
bool die = cf->wall == waRichDie;
|
||||
playSound(ct, "orb-ranged");
|
||||
if(cf->monst)
|
||||
addMessage(XLAT("You blow %the1 away!", cf->monst));
|
||||
if(cf->monst == moVoidBeast)
|
||||
addMessage(XLAT("You blow %the1 closer!", cf->monst));
|
||||
else if(cf->monst)
|
||||
addMessage(XLAT("You blow %the1 away!", cf->monst));
|
||||
if(cf->wall == waThumperOff) activateActiv(cf, false);
|
||||
if(isPushable(cf->wall) || cf->wall == waBigStatue)
|
||||
pushThumper(mi);
|
||||
|
@ -1205,9 +1221,9 @@ EX bool monstersnearO(orbAction a, cell *c) {
|
|||
EX bool isCheck(orbAction a) { return a == roCheck || a == roMultiCheck; }
|
||||
EX bool isWeakCheck(orbAction a) { return a == roCheck || a == roMultiCheck || a == roMouse; }
|
||||
|
||||
EX movei blowoff_destination(cell *c, int& di) {
|
||||
EX movei blowoff_destination_dir(cell *c, int& di, int rev) {
|
||||
int d = 0;
|
||||
for(; d<c->type; d++) if(c->move(d) && c->move(d)->cpdist < c->cpdist) break;
|
||||
for(; d<c->type; d++) if(c->move(d) && rev*c->move(d)->cpdist < rev*c->cpdist) break;
|
||||
if(d<c->type) for(int e=d; e<d+c->type; e++) {
|
||||
int di = e % c->type;
|
||||
cell *c2 = c->move(di);
|
||||
|
@ -1215,11 +1231,16 @@ EX movei blowoff_destination(cell *c, int& di) {
|
|||
if(dice::on(c) && !dice::can_roll(movei(c, di)))
|
||||
continue;
|
||||
#endif
|
||||
if(c2 && c2->cpdist > c->cpdist && passable(c2, c, P_BLOW)) return movei(c, c2, di);
|
||||
if(c2 && rev*c2->cpdist > rev*c->cpdist && passable(c2, c, P_BLOW)) return movei(c, c2, di);
|
||||
}
|
||||
return movei(c, c, NO_SPACE);
|
||||
}
|
||||
|
||||
EX movei blowoff_destination(cell *c, int& di) {
|
||||
int rev = c->monst == moVoidBeast ? -1 : 1;
|
||||
return blowoff_destination_dir(c, di, rev);
|
||||
}
|
||||
|
||||
EX int check_jump(cell *cf, cell *ct, flagtype flags, cell*& jumpthru) {
|
||||
int partial = 1;
|
||||
forCellCM(c2, cf) {
|
||||
|
@ -1510,7 +1531,7 @@ EX eItem targetRangedOrb(cell *c, orbAction a) {
|
|||
}
|
||||
|
||||
if(phasestate == 3) {
|
||||
if(jumpTo(a, c, itOrbPhasing)) phasestate = 4;
|
||||
if(jumpTo(a, c, itOrbPhasing, 0, moNone, jumpthru)) phasestate = 4;
|
||||
else wouldkill_there = true;
|
||||
}
|
||||
else changes.rollback();
|
||||
|
|
|
@ -169,6 +169,7 @@ EX bool passable(cell *w, cell *from, flagtype flags) {
|
|||
if(airdist(w) < 3) return false;
|
||||
if(againstWind(w,from)) return false;
|
||||
if(isGravityLand(w)) return false;
|
||||
if(w->wall == waChasm && w->land == laDual) return false;
|
||||
}
|
||||
|
||||
if(from && strictlyAgainstGravity(w, from, vrevdir, flags)
|
||||
|
@ -258,7 +259,8 @@ EX bool passable(cell *w, cell *from, flagtype flags) {
|
|||
}
|
||||
|
||||
if(isWatery(w)) {
|
||||
if(in_gravity_zone(w)) ;
|
||||
if((flags & P_ISPLAYER) && from && isWatery(from) && pickable_from_water(w->item)) ;
|
||||
else if(in_gravity_zone(w)) ;
|
||||
else if(from && from->wall == waBoat && F(P_USEBOAT) &&
|
||||
(!againstCurrent(w, from) || F(P_MARKWATER)) && !(from->item == itOrbYendor)) ;
|
||||
else if(from && isWatery(from) && F(P_CHAIN) && F(P_USEBOAT) && !againstCurrent(w, from)) ;
|
||||
|
@ -419,6 +421,8 @@ EX bool canPushStatueOn(cell *c, flagtype flags) {
|
|||
}
|
||||
|
||||
EX void moveBoat(const movei& mi) {
|
||||
changes.ccell(mi.t);
|
||||
changes.ccell(mi.s);
|
||||
eWall x = mi.t->wall; mi.t->wall = mi.s->wall; mi.s->wall = x;
|
||||
mi.t->mondir = mi.rev_dir_or(NODIR);
|
||||
moveItem(mi.s, mi.t, false);
|
||||
|
|
972
pattern2.cpp
972
pattern2.cpp
File diff suppressed because it is too large
Load Diff
189
pcmove.cpp
189
pcmove.cpp
|
@ -118,8 +118,9 @@ bool pcmove::checkNeedMove(bool checkonly, bool attacking) {
|
|||
if(items[itOrbDomination] > ORBBASE && cwt.at->monst)
|
||||
return false;
|
||||
int flags = 0;
|
||||
bool drown = false;
|
||||
if(cwt.at->monst) {
|
||||
if(vmsg(miRESTRICTED)) {
|
||||
if(vmsg(miRESTRICTED, siMONSTER, cwt.at, cwt.at->monst)) {
|
||||
if(isMountable(cwt.at->monst))
|
||||
addMessage(XLAT("You need to dismount %the1!", cwt.at->monst));
|
||||
else
|
||||
|
@ -128,60 +129,75 @@ bool pcmove::checkNeedMove(bool checkonly, bool attacking) {
|
|||
}
|
||||
else if(cwt.at->wall == waRoundTable) {
|
||||
if(markOrb2(itOrbAether)) return false;
|
||||
if(vmsg(miRESTRICTED))
|
||||
if(vmsg(miRESTRICTED, siWALL, cwt.at, moNone))
|
||||
addMessage(XLAT("It would be impolite to land on the table!"));
|
||||
}
|
||||
else if(cwt.at->wall == waLake) {
|
||||
drown = true;
|
||||
if(markOrb2(itOrbAether)) return false;
|
||||
if(markOrb2(itOrbFish)) return false;
|
||||
if(in_gravity_zone(cwt.at) && passable(cwt.at, NULL, P_ISPLAYER)) return false;
|
||||
flags |= AF_FALL;
|
||||
if(vmsg(miWALL)) addMessage(XLAT("Ice below you is melting! RUN!"));
|
||||
if(vmsg(miWALL, siWALL, cwt.at, moNone)) addMessage(XLAT("Ice below you is melting! RUN!"));
|
||||
}
|
||||
else if(!attacking && cellEdgeUnstable(cwt.at)) {
|
||||
if(markOrb2(itOrbAether)) return false;
|
||||
if(in_gravity_zone(cwt.at) && passable(cwt.at, NULL, P_ISPLAYER)) return false;
|
||||
if(vmsg(miRESTRICTED)) addMessage(XLAT("Nothing to stand on here!"));
|
||||
if(vmsg(miRESTRICTED, siGRAVITY, cwt.at, moNone)) addMessage(XLAT("Nothing to stand on here!"));
|
||||
return true;
|
||||
}
|
||||
else if(among(cwt.at->wall, waSea, waCamelotMoat, waLake, waDeepWater)) {
|
||||
drown = true;
|
||||
if(markOrb(itOrbFish)) return false;
|
||||
if(markOrb2(itOrbAether)) return false;
|
||||
if(in_gravity_zone(cwt.at) && passable(cwt.at, NULL, P_ISPLAYER)) return false;
|
||||
if(vmsg(miWALL)) addMessage(XLAT("You have to run away from the water!"));
|
||||
if(vmsg(miWALL, siWALL, cwt.at, moNone)) addMessage(XLAT("You have to run away from the water!"));
|
||||
}
|
||||
else if(cwt.at->wall == waClosedGate) {
|
||||
if(markOrb2(itOrbAether)) return false;
|
||||
if(vmsg(miWALL)) addMessage(XLAT("The gate is closing right on you! RUN!"));
|
||||
if(vmsg(miWALL, siWALL, cwt.at, moNone)) addMessage(XLAT("The gate is closing right on you! RUN!"));
|
||||
}
|
||||
else if(isFire(cwt.at) && !markOrb(itOrbWinter) && !markOrb(itCurseWater) && !markOrb2(itOrbShield)) {
|
||||
if(markOrb2(itOrbAether)) return false;
|
||||
if(vmsg(miWALL)) addMessage(XLAT("This spot will be burning soon! RUN!"));
|
||||
if(vmsg(miWALL, siWALL, cwt.at, moNone)) addMessage(XLAT("This spot will be burning soon! RUN!"));
|
||||
}
|
||||
else if(cwt.at->wall == waMagma && !markOrb(itOrbWinter) && !markOrb(itCurseWater) && !markOrb2(itOrbShield)) {
|
||||
if(markOrb2(itOrbAether)) return false;
|
||||
if(in_gravity_zone(cwt.at) && passable(cwt.at, cwt.at, P_ISPLAYER)) return false;
|
||||
if(vmsg(miWALL)) addMessage(XLAT("Run away from the lava!"));
|
||||
if(vmsg(miWALL, siWALL, cwt.at, moNone)) addMessage(XLAT("Run away from the lava!"));
|
||||
}
|
||||
else if(cwt.at->wall == waChasm) {
|
||||
if(markOrb2(itOrbAether)) return false;
|
||||
if(in_gravity_zone(cwt.at) && passable(cwt.at, cwt.at, P_ISPLAYER)) return false;
|
||||
flags |= AF_FALL;
|
||||
if(vmsg(miWALL)) addMessage(XLAT("The floor has collapsed! RUN!"));
|
||||
if(vmsg(miWALL, siWALL, cwt.at, moNone)) addMessage(XLAT("The floor has collapsed! RUN!"));
|
||||
}
|
||||
else if(items[itOrbAether] > ORBBASE && !passable(cwt.at, NULL, P_ISPLAYER | P_NOAETHER)) {
|
||||
if(markOrb2(itOrbAether)) return false;
|
||||
vmsg(miWALL);
|
||||
vmsg(miWALL, siWALL, cwt.at, moNone);
|
||||
return true;
|
||||
}
|
||||
else if(!passable(cwt.at, NULL, P_ISPLAYER)) {
|
||||
if(isFire(cwt.at)) return false; // already checked: have Shield
|
||||
if(markOrb2(itOrbAether)) return false;
|
||||
if(vmsg(miWALL)) addMessage(XLAT("Your Aether power has expired! RUN!"));
|
||||
if(vmsg(miWALL, siWALL, cwt.at, moNone)) addMessage(XLAT("Your Aether power has expired! RUN!"));
|
||||
}
|
||||
else return false;
|
||||
if(hardcore && !checkonly)
|
||||
if(hardcore && !checkonly) {
|
||||
if(cwt.at->monst)
|
||||
yasc_message = XLAT("did not leave %the1", cwt.at->monst);
|
||||
else if(cwt.at->wall == waChasm)
|
||||
yasc_message = XLAT("fell into a chasm");
|
||||
else if(cwt.at->wall == waRoundTable)
|
||||
yasc_message = XLAT("died by politeness");
|
||||
else if(cwt.at->wall == waClosedGate)
|
||||
yasc_message = XLAT("crushed by a gate");
|
||||
else if(drown)
|
||||
yasc_message = XLAT("drowned in %the1", cwt.at->wall);
|
||||
else
|
||||
yasc_message = XLAT("did not leave %the1", cwt.at->wall);
|
||||
killHardcorePlayer(multi::cpid, flags);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -198,6 +214,7 @@ struct pcmove {
|
|||
bool fmsMove, fmsAttack, fmsActivate;
|
||||
int d;
|
||||
int subdir;
|
||||
/** used to tell perform_actual_move() that this is a boat move and thus we should not pick up items */
|
||||
bool boatmove;
|
||||
bool good_tortoise;
|
||||
flagtype attackflags;
|
||||
|
@ -226,16 +243,33 @@ struct pcmove {
|
|||
movei mi, mip;
|
||||
pcmove() : mi(nullptr, nullptr, 0), mip(nullptr, nullptr, 0) {}
|
||||
|
||||
bool vmsg(int code);
|
||||
bool vmsg(moveissue mi);
|
||||
|
||||
bool vmsg(int code, int subissue_code, cell *where, eMonster m) {
|
||||
moveissue mi;
|
||||
mi.type = code;
|
||||
mi.subtype = subissue_code;
|
||||
mi.monster = m;
|
||||
mi.where = where;
|
||||
return vmsg(mi);
|
||||
}
|
||||
|
||||
bool vmsg_threat() {
|
||||
return vmsg(miTHREAT, siMONSTER, who_kills_me_cell, who_kills_me);
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
EX cell *global_pushto;
|
||||
|
||||
bool pcmove::vmsg(int code) { checked_move_issue = code; changes.rollback(); return errormsgs && !checkonly; }
|
||||
bool pcmove::vmsg(moveissue mi) {
|
||||
checked_move_issue = mi;
|
||||
changes.rollback();
|
||||
return errormsgs && !checkonly;
|
||||
}
|
||||
|
||||
EX bool movepcto(int d, int subdir IS(1), bool checkonly IS(false)) {
|
||||
checked_move_issue = miVALID;
|
||||
checked_move_issue.type = miVALID;
|
||||
pcmove pcm;
|
||||
pcm.checkonly = checkonly;
|
||||
pcm.d = d; pcm.subdir = subdir;
|
||||
|
@ -258,6 +292,9 @@ bool pcmove::try_shooting(bool auto_target) {
|
|||
addMessage(XLAT("Fire!"));
|
||||
}
|
||||
items[itCrossbow] = bow::loading_time();
|
||||
cell *fst = cwt.peek();
|
||||
if(bow::bowpath.size() >= 1) fst = bow::bowpath[1].prev.at;
|
||||
eMonster blocked = fst->monst;
|
||||
bow::shoot();
|
||||
|
||||
int v = -1; for(auto p: bow::bowpath) if(p.next.at == cwt.at && (p.flags & bow::bpFIRST)) v = p.next.spin;
|
||||
|
@ -268,6 +305,13 @@ bool pcmove::try_shooting(bool auto_target) {
|
|||
if(gravity_state) markOrb(itOrbGravity);
|
||||
}
|
||||
|
||||
if(againstRose(cwt.at, nullptr) && !scentResistant() && (againstRose(cwt.at, fst) || blocked == fst->monst)) {
|
||||
if(vmsg(miRESTRICTED, siROSE, nullptr, moNone)) {
|
||||
addMessage(XLAT("You cannot stay in place and shoot, those roses smell too nicely.") + its(celldistance(cwt.at, fst)));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if(cellEdgeUnstable(cwt.at) || cwt.at->land == laWhirlpool) {
|
||||
if(checkonly) return true;
|
||||
if(changes.on) changes.commit();
|
||||
|
@ -282,12 +326,14 @@ bool pcmove::try_shooting(bool auto_target) {
|
|||
nextmovetype = hit_anything ? lmAttack : lmSkip;
|
||||
lastmovetype = hit_anything ? lmAttack : lmSkip; lastmove = NULL;
|
||||
|
||||
while(bow::rusalka_curses--) rusalka_curse();
|
||||
|
||||
mi = movei(cwt.at, STAY);
|
||||
if(last_gravity_state && !gravity_state)
|
||||
playerMoveEffects(mi);
|
||||
|
||||
if(monstersnear_add_pmi(mi)) {
|
||||
if(vmsg(miTHREAT)) wouldkill("%The1 would catch you!");
|
||||
if(vmsg_threat()) wouldkill("%The1 would catch you!");
|
||||
return false;
|
||||
}
|
||||
if(checkonly) return true;
|
||||
|
@ -330,7 +376,7 @@ bool pcmove::movepcto() {
|
|||
if(againstRose(cwt.at, NULL) && d<0 && !scentResistant()) {
|
||||
fatigued = items[itFatigue] >= 8;
|
||||
if(!fatigued) {
|
||||
if(vmsg(miRESTRICTED))
|
||||
if(vmsg(miRESTRICTED, siROSE, nullptr, moNone))
|
||||
addMessage(XLAT("You just cannot stand in place, those roses smell too nicely."));
|
||||
return false;
|
||||
}
|
||||
|
@ -444,7 +490,7 @@ bool pcmove::swing() {
|
|||
mirror::act(origd, mirror::SPINMULTI | mirror::ATTACK);
|
||||
|
||||
if(monstersnear_add_pmi(movei(cwt.at, STAY))) {
|
||||
if(vmsg(miTHREAT))
|
||||
if(nextmovetype == lmAttack ? vmsg(miWALL, siWALL, mi.t, who_kills_me) : vmsg_threat())
|
||||
wouldkill("You would be killed by %the1!");
|
||||
return false;
|
||||
}
|
||||
|
@ -670,6 +716,11 @@ void apply_chaos() {
|
|||
markOrb(itOrbChaos);
|
||||
copy_metadata(ca, &cob);
|
||||
copy_metadata(cb, &coa);
|
||||
|
||||
ca->item = coa.item;
|
||||
cb->item = cob.item;
|
||||
moveItem(ca, cb, false);
|
||||
|
||||
if(!switch_lhu_in(ca->land)) ca->LHU = coa.LHU;
|
||||
if(!switch_lhu_in(cb->land)) cb->LHU = cob.LHU;
|
||||
if(ca->monst && !(isFriendly(ca) && markOrb(itOrbEmpathy))) {
|
||||
|
@ -694,9 +745,6 @@ void apply_chaos() {
|
|||
if(dice::on(ca) || dice::on(cb)) {
|
||||
dice::chaos_swap(wa, wb);
|
||||
}
|
||||
if(ca->item == itBabyTortoise || cb->item == itBabyTortoise) {
|
||||
tortoise::move_baby(ca, cb);
|
||||
}
|
||||
}
|
||||
|
||||
bool pcmove::actual_move() {
|
||||
|
@ -724,7 +772,7 @@ bool pcmove::actual_move() {
|
|||
}
|
||||
|
||||
if(againstRose(cwt.at, c2) && !scentResistant()) {
|
||||
if(vmsg(miRESTRICTED)) addMessage("Those roses smell too nicely. You have to come towards them.");
|
||||
if(vmsg(miRESTRICTED, siROSE, nullptr, moNone)) addMessage("Those roses smell too nicely. You have to come towards them.");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -755,6 +803,16 @@ bool pcmove::actual_move() {
|
|||
c2->monst = moNone;
|
||||
c2->wall = waRichDie;
|
||||
}
|
||||
else {
|
||||
if(vmsg(miWALL, siWALL, c2, c2->monst))
|
||||
addMessage(XLAT("You can only push this die if the highest number would be on the top!"));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if(mip.d == NO_SPACE) {
|
||||
if(vmsg(miWALL, siWALL, c2, c2->monst))
|
||||
addMessage(XLAT("No room to push %the1.", c2->monst));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -763,7 +821,7 @@ bool pcmove::actual_move() {
|
|||
mip = determinePush(cwt, subdir, [] (movei mi) { return canPushThumperOn(mi, cwt.at); });
|
||||
if(mip.t) changes.ccell(mip.t);
|
||||
if(mip.d == NO_SPACE) {
|
||||
if(vmsg(miWALL)) addMessage(XLAT("No room to push %the1.", c2->wall));
|
||||
if(vmsg(miWALL, siWALL, c2, moNone)) addMessage(XLAT("No room to push %the1.", c2->wall));
|
||||
return false;
|
||||
}
|
||||
nextmovetype = lmMove;
|
||||
|
@ -775,7 +833,7 @@ bool pcmove::actual_move() {
|
|||
}
|
||||
|
||||
if(c2->item == itHolyGrail && roundTableRadius(c2) < newRoundTableRadius()) {
|
||||
if(vmsg(miRESTRICTED)) addMessage(XLAT("That was not a challenge. Find a larger castle!"));
|
||||
if(vmsg(miRESTRICTED, siITEM, c2, moNone)) addMessage(XLAT("That was not a challenge. Find a larger castle!"));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -787,13 +845,10 @@ bool pcmove::actual_move() {
|
|||
return boat_move();
|
||||
|
||||
if(!c2->monst && cwt.at->wall == waBoat && cwt.at->item != itOrbYendor && boatGoesThrough(c2) && markOrb(itOrbWater) && !nonAdjacentPlayer(c2, cwt.at) && fmsMove) {
|
||||
|
||||
if(c2->item && !cwt.at->item) moveItem(c2, cwt.at, false), boatmove = true;
|
||||
placeWater(c2, cwt.at);
|
||||
moveBoat(mi);
|
||||
if(c2->item && collectItem(c2, cwt.at)) return true;
|
||||
changes.ccell(c2);
|
||||
c2->mondir = revhint(cwt.at, d);
|
||||
if(c2->item) boatmove = !boatmove;
|
||||
placeWater(c2, cwt.at);
|
||||
moveBoat(mi); boatmove = true;
|
||||
return perform_actual_move();
|
||||
}
|
||||
|
||||
|
@ -815,21 +870,21 @@ bool pcmove::boat_move() {
|
|||
cell *& c2 = mi.t;
|
||||
|
||||
if(againstWind(c2, cwt.at)) {
|
||||
if(vmsg(miRESTRICTED)) blowaway_message(c2);
|
||||
if(vmsg(miRESTRICTED, siWIND, c2, moNone)) blowaway_message(c2);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(againstCurrent(c2, cwt.at) && !markOrb(itOrbWater)) {
|
||||
if(markOrb(itOrbFish) || markOrb(itOrbAether) || gravity_state)
|
||||
return after_escape();
|
||||
if(vmsg(miRESTRICTED)) addMessage(XLAT("You cannot go against the current!"));
|
||||
if(vmsg(miRESTRICTED, siCURRENT, c2, moNone)) addMessage(XLAT("You cannot go against the current!"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if(cwt.at->item == itOrbYendor) {
|
||||
if(markOrb(itOrbFish) || markOrb(itOrbAether) || gravity_state)
|
||||
return after_escape();
|
||||
if(vmsg(miRESTRICTED)) addMessage(XLAT("The Orb of Yendor is locked in with powerful magic."));
|
||||
if(vmsg(miRESTRICTED, siITEM, c2, moNone)) addMessage(XLAT("The Orb of Yendor is locked in with powerful magic."));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -874,8 +929,6 @@ void pcmove::tell_why_cannot_attack() {
|
|||
addMessage(XLAT("You cannot attack Raiders directly!"));
|
||||
else if(isSwitch(c2->monst))
|
||||
addMessage(XLAT("You cannot attack Jellies in their wall form!"));
|
||||
else if(c2->monst == moAnimatedDie)
|
||||
addMessage(XLAT("You can only push this die if the highest number would be on the top!"));
|
||||
else if(c2->monst == moAngryDie)
|
||||
addMessage(XLAT("This die is really angry at you!"));
|
||||
else if((attackflags & AF_WEAK) && isIvy(c2))
|
||||
|
@ -904,7 +957,7 @@ bool pcmove::after_escape() {
|
|||
if(push_behind && !c2->monst && !nonAdjacentPlayer(c2, cwt.at) && fmsMove) {
|
||||
eWall what = c2->wall;
|
||||
if(!thruVine(c2, cwt.at) && !canPushStatueOn(cwt.at, P_ISPLAYER)) {
|
||||
if(vmsg(miRESTRICTED)) {
|
||||
if(vmsg(miRESTRICTED, siWALL, c2, moNone)) {
|
||||
if(isFire(cwt.at))
|
||||
addMessage(XLAT("You have to escape first!"));
|
||||
else
|
||||
|
@ -988,7 +1041,7 @@ bool pcmove::after_escape() {
|
|||
}
|
||||
else if(c2->monst == moKnight) {
|
||||
#if CAP_COMPLEX2
|
||||
if(vmsg(miWALL)) camelot::knightFlavorMessage(c2);
|
||||
if(vmsg(miWALL, siMONSTER, c2, c2->monst)) camelot::knightFlavorMessage(c2);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
@ -999,7 +1052,7 @@ bool pcmove::after_escape() {
|
|||
return false;
|
||||
}
|
||||
else if(markOrb(itCurseFatigue) && items[itFatigue] + fatigue_cost(mi) > 10) {
|
||||
if(vmsg(miRESTRICTED))
|
||||
if(vmsg(miRESTRICTED, siFATIGUE, nullptr, moNone))
|
||||
addMessage(XLAT("You are too fatigued!"));
|
||||
return false;
|
||||
}
|
||||
|
@ -1035,45 +1088,51 @@ bool pcmove::move_if_okay() {
|
|||
void pcmove::tell_why_impassable() {
|
||||
cell*& c2 = mi.t;
|
||||
if(nonAdjacentPlayer(cwt.at,c2)) {
|
||||
if(vmsg(miRESTRICTED)) addMessage(geosupport_football() < 2 ?
|
||||
if(vmsg(miRESTRICTED, siWARP, c2, moNone)) addMessage(geosupport_football() < 2 ?
|
||||
XLAT("You cannot move between the cells without dots here!") :
|
||||
XLAT("You cannot move between the triangular cells here!")
|
||||
);
|
||||
}
|
||||
else if(againstWind(c2, cwt.at)) {
|
||||
if(vmsg(miRESTRICTED))
|
||||
if(vmsg(miRESTRICTED, siWIND, c2, moNone))
|
||||
blowaway_message(c2);
|
||||
}
|
||||
else if(anti_alchemy(c2, cwt.at)) {
|
||||
if(vmsg(miRESTRICTED))
|
||||
if(vmsg(miRESTRICTED, siWALL, c2, moNone))
|
||||
addMessage(XLAT("Wrong color!"));
|
||||
}
|
||||
else if(c2->wall == waRoundTable) {
|
||||
if(vmsg(miRESTRICTED))
|
||||
if(vmsg(miRESTRICTED, siWALL, c2, moNone))
|
||||
addMessage(XLAT("It would be impolite to land on the table!"));
|
||||
}
|
||||
else if(snakelevel(cwt.at) >= 3 && snakelevel(c2) == 0 && !isWall(c2)) {
|
||||
if(vmsg(miRESTRICTED))
|
||||
if(vmsg(miRESTRICTED, siWALL, cwt.at, moNone))
|
||||
addMessage(XLAT("You would get hurt!", c2->wall));
|
||||
}
|
||||
else if(cellEdgeUnstable(cwt.at) && cellEdgeUnstable(c2)) {
|
||||
if(vmsg(miRESTRICTED))
|
||||
if(vmsg(miRESTRICTED, siGRAVITY, c2, moNone))
|
||||
addMessage(XLAT("Gravity does not allow this!"));
|
||||
}
|
||||
else if(c2->wall == waChasm && c2->land == laDual) {
|
||||
if(vmsg(miRESTRICTED))
|
||||
if(vmsg(miRESTRICTED, siWALL, c2, moNone))
|
||||
addMessage(XLAT("You cannot move there!"));
|
||||
}
|
||||
else if(!c2->wall) {
|
||||
if(vmsg(miRESTRICTED))
|
||||
if(vmsg(miRESTRICTED, siUNKNOWN, c2, moNone))
|
||||
addMessage(XLAT("You cannot move there!"));
|
||||
}
|
||||
else {
|
||||
if(vmsg(miWALL))
|
||||
if(vmsg(miWALL, siWALL, c2, moNone))
|
||||
addMessage(XLAT("You cannot move through %the1!", c2->wall));
|
||||
}
|
||||
}
|
||||
|
||||
EX void rusalka_curse() {
|
||||
changes.ccell(cwt.at);
|
||||
if(cwt.at->wall == waNone) cwt.at->wall = waShallow;
|
||||
else if(cwt.at->wall == waShallow || isAlch(cwt.at->wall)) cwt.at->wall = waDeepWater;
|
||||
}
|
||||
|
||||
bool pcmove::attack() {
|
||||
auto& c2 = mi.t;
|
||||
if(!fmsAttack) return false;
|
||||
|
@ -1091,14 +1150,14 @@ bool pcmove::attack() {
|
|||
if(!ca) {
|
||||
if(forcedmovetype == fmAttack) {
|
||||
if(monstersnear_add_pmi(movei(cwt.at, STAY))) {
|
||||
if(vmsg(miTHREAT)) wouldkill("%The1 would get you!");
|
||||
if(vmsg_threat()) wouldkill("%The1 would get you!");
|
||||
return false;
|
||||
}
|
||||
nextmovetype = lmSkip;
|
||||
addMessage(XLAT("You swing your sword at %the1.", c2->monst));
|
||||
return swing();
|
||||
}
|
||||
if(vmsg(miENTITY)) tell_why_cannot_attack();
|
||||
if(vmsg(miENTITY, siMONSTER, c2, c2->monst)) tell_why_cannot_attack();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1150,11 +1209,7 @@ bool pcmove::attack() {
|
|||
changes.value_add(wandering_jiangshi, 1);
|
||||
}
|
||||
attackMonster(c2, attackflags | AF_MSG, moPlayer);
|
||||
if(m == moRusalka) {
|
||||
changes.ccell(cwt.at);
|
||||
if(cwt.at->wall == waNone) cwt.at->wall = waShallow;
|
||||
else if(cwt.at->wall == waShallow || isAlch(cwt.at->wall)) cwt.at->wall = waDeepWater;
|
||||
}
|
||||
if(m == moRusalka) rusalka_curse();
|
||||
changes.ccell(c2);
|
||||
// salamanders are stunned for longer time when pushed into a wall
|
||||
if(c2->monst == moSalamander && (mip.t == c2 || !mip.t)) c2->stuntime = 10;
|
||||
|
@ -1172,7 +1227,7 @@ bool pcmove::attack() {
|
|||
swordAttackStatic();
|
||||
|
||||
if(monstersnear_add_pmi(movei(cwt.at, STAY))) {
|
||||
if(vmsg(miTHREAT)) wouldkill("You would be killed by %the1!");
|
||||
if(vmsg_threat()) wouldkill("You would be killed by %the1!");
|
||||
return false;
|
||||
}
|
||||
if(checkonly) return true;
|
||||
|
@ -1236,21 +1291,15 @@ bool pcmove::perform_actual_move() {
|
|||
handle_friendly_ivy();
|
||||
|
||||
if(items[itOrbDigging]) {
|
||||
invismove = false;
|
||||
if(earthMove(mi)) markOrb(itOrbDigging);
|
||||
if(earthMove(mi)) {
|
||||
invismove = false;
|
||||
markOrb(itOrbDigging);
|
||||
}
|
||||
}
|
||||
|
||||
movecost(cwt.at, c2, 1);
|
||||
|
||||
if(!boatmove && collectItem(c2, cwt.at)) return true;
|
||||
if(boatmove && c2->item && cwt.at->item) {
|
||||
eItem it = c2->item;
|
||||
c2->item = cwt.at->item;
|
||||
if(collectItem(c2, cwt.at)) return true;
|
||||
eItem it2 = c2->item;
|
||||
c2->item = it;
|
||||
cwt.at->item = it2;
|
||||
}
|
||||
if(doPickupItemsWithMagnetism(c2)) return true;
|
||||
|
||||
if(isIcyLand(cwt.at) && cwt.at->wall == waNone && markOrb(itOrbWinter)) {
|
||||
|
@ -1262,7 +1311,11 @@ bool pcmove::perform_actual_move() {
|
|||
forCellEx(c3, c2) if(c3->wall == waIcewall && c3->item) {
|
||||
changes.ccell(c3);
|
||||
markOrb(itOrbWinter);
|
||||
if(collectItem(c3, cwt.at)) return true;
|
||||
eItem it = c3->item;
|
||||
if(collectItem(c3, cwt.at))
|
||||
return true;
|
||||
if(!c3->item)
|
||||
animate_item_throw(c3, c2, it);
|
||||
}
|
||||
|
||||
movecost(cwt.at, c2, 2);
|
||||
|
@ -1312,7 +1365,7 @@ bool pcmove::perform_move_or_jump() {
|
|||
if(mi.t->monst == moFriendlyIvy) changes.ccell(mi.t), mi.t->monst = moNone;
|
||||
|
||||
if(monstersnear_add_pmi(pmi)) {
|
||||
if(vmsg(miTHREAT)) wouldkill("%The1 would kill you there!");
|
||||
if(vmsg_threat()) wouldkill("%The1 would kill you there!");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1357,7 +1410,7 @@ bool pcmove::stay() {
|
|||
items[itFatigue] = 0;
|
||||
|
||||
if(monstersnear_add_pmi(mi)) {
|
||||
if(vmsg(miTHREAT)) wouldkill("%The1 would get you!");
|
||||
if(vmsg_threat()) wouldkill("%The1 would get you!");
|
||||
return false;
|
||||
}
|
||||
if(checkonly) return true;
|
||||
|
|
21
quit.cpp
21
quit.cpp
|
@ -32,6 +32,17 @@ EX string getgametime_s(int timespent IS(getgametime())) {
|
|||
|
||||
EX bool display_yasc_codes;
|
||||
|
||||
string formatted_yasc_code() {
|
||||
if(yasc_code < 100000) return its(yasc_code);
|
||||
int y = yasc_code;
|
||||
string out;
|
||||
while(y >= 100) {
|
||||
out = "-" + its(y%100) + out;
|
||||
y /= 100;
|
||||
}
|
||||
return its(y) + out;
|
||||
}
|
||||
|
||||
string timeline() {
|
||||
string s;
|
||||
if(shmup::on)
|
||||
|
@ -39,7 +50,7 @@ string timeline() {
|
|||
else {
|
||||
s = XLAT("%1 turns (%2)", its(turncount), getgametime_s());
|
||||
if(display_yasc_codes)
|
||||
s+= XLAT(" YASC code: ") + its(yasc_code);
|
||||
s += XLAT(" YASC code: ") + formatted_yasc_code();
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
@ -321,13 +332,14 @@ EX void showGameMenu() {
|
|||
#if CAP_TOUR
|
||||
tour::on ? (canmove ? XLAT("guided tour") : XLAT("GAME OVER")) :
|
||||
#endif
|
||||
(cheater && !autocheat)? XLAT("It is a shame to cheat!") :
|
||||
(cheater && !autocheat) ? XLAT("It is a shame to cheat!") :
|
||||
racing::on ? "racing mode" :
|
||||
(canmove && princess::challenge) ? XLAT("%1 Challenge", moPrincess) :
|
||||
canmove ? XLAT("Quest status") :
|
||||
XLAT("GAME OVER"),
|
||||
0xC00000, 200, 100
|
||||
);
|
||||
if(!canmove && yasc_message != "") dialog::addInfo(yasc_message);
|
||||
|
||||
#if CAP_COMPLEX2
|
||||
bool sweeper = mine::in_minesweeper();
|
||||
|
@ -433,7 +445,7 @@ EX void showGameMenu() {
|
|||
if(cheater && !autocheat) {
|
||||
dialog::addInfo(XLAT("you have cheated %1 times", its(cheater)), 0xFF2020);
|
||||
}
|
||||
else if(!racing::on) {
|
||||
if(!racing::on) {
|
||||
dialog::addInfo(timeline(), dialog::dialogcolor);
|
||||
}
|
||||
|
||||
|
@ -638,7 +650,8 @@ EX void handleKeyQuit(int sym, int uni) {
|
|||
popScreen();
|
||||
msgs.clear();
|
||||
if(!canmove) {
|
||||
addMessage(XLAT("GAME OVER"));
|
||||
if(yasc_message != "") addMessage(XLAT("GAME OVER") + ": " + yasc_message);
|
||||
else addMessage(XLAT("GAME OVER"));
|
||||
addMessage(timeline());
|
||||
}
|
||||
}
|
||||
|
|
11
racing.cpp
11
racing.cpp
|
@ -1039,10 +1039,15 @@ void race_projection() {
|
|||
if(GDIM == 2) {
|
||||
dialog::addMatrixItem(XLAT("race angle"), race_angle.get(), 'a');
|
||||
dialog::add_action([] () {
|
||||
dialog::editMatrix(race_angle.get(), XLAT("model orientation"), "", GDIM);
|
||||
dialog::editMatrix(race_angle.get(), XLAT("race angle"), "", GDIM);
|
||||
auto& d = dialog::get_di();
|
||||
auto q = rot_inverse(race_angle) * pconf.mori();
|
||||
auto last = dialog::get_ne().reaction;
|
||||
dialog::get_ne().reaction = [q, last] () { last(); pconf.mori() = race_angle * q; };
|
||||
auto last = d.reaction;
|
||||
d.reaction = [q, last] () {
|
||||
if(last) last();
|
||||
pconf.mori() = race_angle * q;
|
||||
if(racing::on) set_view();
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
|
|
25
radar.cpp
25
radar.cpp
|
@ -2,7 +2,7 @@
|
|||
namespace hr {
|
||||
|
||||
#if MAXMDIM >= 4
|
||||
pair<bool, hyperpoint> makeradar(shiftpoint h) {
|
||||
pair<bool, hyperpoint> makeradar(shiftpoint h, bool distant) {
|
||||
|
||||
hyperpoint h1;
|
||||
|
||||
|
@ -23,8 +23,13 @@ pair<bool, hyperpoint> makeradar(shiftpoint h) {
|
|||
|
||||
if(WDIM == 3) {
|
||||
ld d = hdist0(h);
|
||||
if(d >= vid.radarrange) return {false, h1};
|
||||
if(d) h1 = h1 * (d / vid.radarrange / hypot_d(3, h1));
|
||||
if(distant) {
|
||||
h1 = h1 / hypot_d(3, h1);
|
||||
}
|
||||
else {
|
||||
if(d >= vid.radarrange) return {false, h1};
|
||||
if(d) h1 = h1 * (d / vid.radarrange / hypot_d(3, h1));
|
||||
}
|
||||
}
|
||||
else {
|
||||
h1 = cgi.emb->actual_to_base(h1);
|
||||
|
@ -45,16 +50,16 @@ pair<bool, hyperpoint> makeradar(shiftpoint h) {
|
|||
return {true, h1};
|
||||
}
|
||||
|
||||
EX void addradar(const shiftmatrix& V, char ch, color_t col, color_t outline) {
|
||||
EX void addradar(const shiftmatrix& V, char ch, color_t col, color_t outline, bool distant IS(false)) {
|
||||
shiftpoint h = V * tile_center();
|
||||
auto hp = makeradar(h);
|
||||
auto hp = makeradar(h, distant);
|
||||
if(hp.first)
|
||||
current_display->radarpoints.emplace_back(radarpoint{hp.second, ch, col, outline});
|
||||
}
|
||||
|
||||
EX void addradar(const shiftpoint h1, const shiftpoint h2, color_t col) {
|
||||
auto hp1 = makeradar(h1);
|
||||
auto hp2 = makeradar(h2);
|
||||
auto hp1 = makeradar(h1, false);
|
||||
auto hp2 = makeradar(h2, false);
|
||||
if(hp1.first && hp2.first)
|
||||
current_display->radarlines.emplace_back(radarline{hp1.second, hp2.second, col});
|
||||
}
|
||||
|
@ -146,7 +151,7 @@ EX void draw_radar(bool cornermode) {
|
|||
auto compassdir = [&] (char dirname, hyperpoint h) {
|
||||
h = NLP * h * .8;
|
||||
queueline(sId*atscreenpos(cx+rad * h[0], cy - rad * h[2] * si + rad * h[1] * co, 0)*C0, sId*atscreenpos(cx+rad*h[0], cy - rad*h[2] * si, 0)*C0, 0xA0401040, -1);
|
||||
displaychr(int(cx+rad * h[0]), int(cy - rad * h[2] * si + rad * h[1] * co), 0, 8, dirname, 0xA04010);
|
||||
displaychr(int(cx+rad * h[0]), int(cy - rad * h[2] * si + rad * h[1] * co), 0, 8 * mapfontscale / 100, dirname, 0xA04010);
|
||||
};
|
||||
compassdir('E', point3(+1, 0, 0));
|
||||
compassdir('N', point3(0, +1, 0));
|
||||
|
@ -180,10 +185,10 @@ EX void draw_radar(bool cornermode) {
|
|||
glflush();
|
||||
|
||||
for(auto& r: cd->radarpoints) {
|
||||
if(d3) displaychr(int(cx + rad * r.h[0]), int(cy - rad * r.h[2] * si + rad * r.h[1] * co), 0, 8, r.glyph, r.color);
|
||||
if(d3) displaychr(int(cx + rad * r.h[0]), int(cy - rad * r.h[2] * si + rad * r.h[1] * co), 0, 8 * mapfontscale / 100, r.glyph, r.color);
|
||||
else {
|
||||
hyperpoint h = locate(r.h);
|
||||
displaychr(int(h[0]), int(h[1]), 0, int(h[2]) / divby, r.glyph, r.color);
|
||||
displaychr(int(h[0]), int(h[1]), 0, int(h[2]) * mapfontscale / divby / 100, r.glyph, r.color);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
9
reg3.cpp
9
reg3.cpp
|
@ -2585,13 +2585,13 @@ int celldistance_534(cell *c1, cell *c2) {
|
|||
|
||||
vector<cell*> s1 = {c1};
|
||||
vector<cell*> s2 = {c2};
|
||||
int best = 99999999;
|
||||
int best = DISTANCE_UNKNOWN_BIG;
|
||||
int d0 = 0;
|
||||
|
||||
auto go_nearer = [&] (vector<cell*>& v, int& d) {
|
||||
vector<cell*> w;
|
||||
for(cell *c: v)
|
||||
forCellEx(c1, c)
|
||||
for(cell *c: v)
|
||||
forCellCM(c1, c)
|
||||
if(celldist(c1) < d)
|
||||
w.push_back(c1);
|
||||
sort(w.begin(), w.end());
|
||||
|
@ -2601,7 +2601,7 @@ int celldistance_534(cell *c1, cell *c2) {
|
|||
v = w;
|
||||
};
|
||||
|
||||
while(d0 < best) {
|
||||
while(d0 < best) {
|
||||
for(cell *a1: s1) for(cell *a2: s2) {
|
||||
if(a1 == a2) best = min(best, d0);
|
||||
else if(isNeighbor(a1, a2)) best = min(best, d0+1);
|
||||
|
@ -2612,6 +2612,7 @@ int celldistance_534(cell *c1, cell *c2) {
|
|||
if(d1 >= d2) go_nearer(s1, d1);
|
||||
if(d1 < d2) go_nearer(s2, d2);
|
||||
}
|
||||
if(best == DISTANCE_UNKNOWN_BIG) best = DISTANCE_UNKNOWN; /* just in case */
|
||||
|
||||
return best;
|
||||
}
|
||||
|
|
|
@ -643,7 +643,7 @@ bool view_ads_ca() {
|
|||
flatresult center;
|
||||
vector<flatresult> hlist;
|
||||
|
||||
color_t statecolor;
|
||||
color_t statecolor = 0;
|
||||
if(1) {
|
||||
dynamicval<eGeometry> b(geometry, gRotSpace);
|
||||
shiftmatrix S = where_matrix[c];
|
||||
|
@ -750,7 +750,7 @@ bool view_ads_ca() {
|
|||
break;
|
||||
}
|
||||
}
|
||||
addaura(shiftless(center.h), statecolor, 0);
|
||||
addaura(shiftless(center.h), statecolor, 0); // todo statecolor not changed
|
||||
}
|
||||
if(acc) {
|
||||
poly_outline = 0xFF;
|
||||
|
|
|
@ -46,8 +46,7 @@ void run_sb() {
|
|||
crystal::set_crystal(6);
|
||||
set_variation(eVariation::pure);
|
||||
enable_canvas();
|
||||
patterns::whichCanvas = 'g';
|
||||
patterns::canvasback = 0x101010;
|
||||
ccolor::set_plain(0x101010);
|
||||
check_cgi();
|
||||
start_game();
|
||||
|
||||
|
|
|
@ -342,7 +342,7 @@ void compute_betweenness(bool verify) {
|
|||
auto b = betweenness3(c1);
|
||||
// add_to_set(c1, 1, 0);
|
||||
auto b4 = betweenness4(c1);
|
||||
print(hlog, hr::format("B;%10Ld;%10Ld;%20.10Lf;%3d;%-40s", b.first, b.second, b4, vertices[i]->lev, rogueviz::vdata[i].name.c_str()));
|
||||
print(hlog, hr::format("B;%10lld;%10lld;%20.10f;%3d;%-40s", b.first, b.second, (double) b4, vertices[i]->lev, rogueviz::vdata[i].name.c_str()));
|
||||
if(verify) {
|
||||
/*
|
||||
betweenness_type a = b.first;
|
||||
|
|
|
@ -86,7 +86,8 @@ int movearound() {
|
|||
int move_restart() {
|
||||
indenter_finish im("move_restart");
|
||||
ld llo = loglik_chosen();
|
||||
array<array<int, 128>, 2> distances_map = {0};
|
||||
array<array<int, 128>, 2> distances_map;
|
||||
for(int a=0; a<2; a++) for(int b=0; b<128; b++) distances_map[a][b] = 0;
|
||||
int moves = 0;
|
||||
// int im = 0;
|
||||
|
||||
|
@ -319,7 +320,7 @@ void load_embedded(const string s) {
|
|||
while(true) {
|
||||
char who[500], where[500];
|
||||
who[0] = 0;
|
||||
fscanf(f, "%s%s", who, where);
|
||||
if(fscanf(f, "%s%s", who, where) < 0) throw hstream_exception("error loading embedding");
|
||||
if(who[0] == 0) break;
|
||||
if(!ids.count(who)) printf("unknown vertex: %s\n", who);
|
||||
string wh = where;
|
||||
|
|
|
@ -139,8 +139,7 @@ void cellcoords() {
|
|||
// needs cellcoords/rvcoords/origcoords
|
||||
void build_disttable() {
|
||||
indenter_finish im("build_disttable");
|
||||
int tab[N];
|
||||
for(int i=0; i<N; i++) tab[i] = N;
|
||||
vector<int> tab(N, N);
|
||||
disttable0.clear();
|
||||
disttable1.clear();
|
||||
|
||||
|
@ -269,7 +268,7 @@ void writestats() {
|
|||
ld placement_loglik = loglik_placement();
|
||||
|
||||
for(int u=0; u<MAXDIST; u++) if(tally[u]) {
|
||||
println(hlog, hr::format("* %4d: %8d / %12Ld = %lf %.10" PLDF " %.10" PLDF,
|
||||
println(hlog, hr::format("* %4d: %8d / %12lld = %lf %.10" PLDF " %.10" PLDF,
|
||||
u, edgetally[u], tally[u], double(edgetally[u]) / tally[u],
|
||||
saved_logistic.yes(u), current_logistic.yes(u)));
|
||||
}
|
||||
|
@ -338,8 +337,7 @@ void build_disttable_approx() {
|
|||
for(int k=0; k<threads; k++)
|
||||
v.emplace_back([&,k] () {
|
||||
auto& dt = results[k];
|
||||
int tab[N];
|
||||
for(int i=0; i<N; i++) tab[i] = N;
|
||||
vector<int> tab(N, N);
|
||||
auto p = k ? nullptr : new progressbar(N/threads, "build_disttable_approx");
|
||||
for(int i=k; i<N; i+=threads) {
|
||||
if(p) (*p)++;
|
||||
|
|
|
@ -53,7 +53,7 @@ void test_paths(int radius) {
|
|||
add_to_tally(mc2, 1, 0);
|
||||
// int v = 0;
|
||||
if(tally[quickdist(mc1, mc2)] != 1) {
|
||||
printf("[%p] [%p]\n", mc1, mc2);
|
||||
printf("[%p] [%p]\n", (void*) mc1, (void*) mc2);
|
||||
printf("quickdist = %d\n", quickdist(mc1, mc2));
|
||||
for(int i=0; i<MAXDIST; i++) if(tally[i]) printf("in tally = %d\n", i);
|
||||
mc1->ascell()->item = itDiamond;
|
||||
|
|
|
@ -35,6 +35,9 @@ struct embset {
|
|||
string name;
|
||||
geom3::eSpatialEmbedding se;
|
||||
ld walls, scale, depth, eye, sun, sky, star;
|
||||
embset(const string& n, geom3::eSpatialEmbedding se, ld walls, ld scale, ld depth, ld eye, ld sun, ld sky, ld star) :
|
||||
name(n), se(se), walls(walls), scale(scale), depth(depth), eye(eye), sun(sun), sky(sky), star(star) {}
|
||||
embset() {}
|
||||
};
|
||||
|
||||
embset current() {
|
||||
|
@ -94,30 +97,30 @@ void print(hstream& hs, const embset& e) {
|
|||
print(hlog, "embset{.name=\"", e.name, "\", .se=eEmbeddingMethod(", int(e.se), "), .walls=", e.walls, ", .scale=", e.scale, ", .depth=", e.depth, ", .eye=", e.eye, ", .sun=", e.sun, ", .sky=", e.sky, ", .star=", e.star, "}");
|
||||
}
|
||||
|
||||
embset edefault = embset{.name="default", .se=geom3::seDefault, .walls=1.2, .scale=0, .depth=0, .eye=1.5, .sun=0.333333, .sky=10, .star=9};
|
||||
embset edefaulti = embset{.name="default", .se=geom3::seDefault, .walls=-1.2, .scale=0, .depth=0, .eye=-1.5, .sun=0.333333, .sky=10, .star=9};
|
||||
embset edefault = embset("default", geom3::seDefault, 1.2, 0, 0, 1.5, 0.333333, 10, 9);
|
||||
embset edefaulti = embset("default", geom3::seDefault, -1.2, 0, 0, 1.5, 0.333333, 10, 9);
|
||||
// embset eincyl = embset{.name="in cylinder", .se=geom3::seCylinderE, .walls=0.75, .scale=M_PI/10, .depth=0, .eye=1.5, .sun=0.10472, .sky=4, .star=3.6};
|
||||
embset eincyl = embset{.name="in cylinder E", .se=geom3::seCylinderE, .walls=1.2, .scale=M_PI/10, .depth=0, .eye=1.5, .sun=0.10472, .sky=2.6, .star=2.4};
|
||||
embset eoutcyl = embset{.name="out cylinder E", .se=geom3::seCylinderE, .walls=-1.2, .scale=M_PI/10, .depth=0, .eye=1.5, .sun=0.3, .sky=10, .star=9};
|
||||
embset eouthoro = embset{.name="out horosphere", .se=geom3::seLowerCurvature, .walls=1.2, .scale=0.1, .depth=0, .eye=1.5, .sun=0.25, .sky=8, .star=7.5};
|
||||
embset einhoro = embset{.name="in horosphere", .se=geom3::seLowerCurvature, .walls=-1.2, .scale=0.1, .depth=0, .eye=1.5, .sun=0.25, .sky=12, .star=11};
|
||||
embset einhoro_small = embset{.name="in horosphere (small sky)", .se=geom3::seLowerCurvature, .walls=-1.2, .scale=0.1, .depth=0, .eye=1.5, .sun=0.25, .sky=18, .star=17};
|
||||
embset esolv = embset{.name="solv", .se=geom3::seSol, .walls=1.2, .scale=0.1, .depth=0, .eye=1.5, .sun=0.25, .sky=12, .star=11};
|
||||
embset einnih = embset{.name="in NIH", .se=geom3::seNIH, .walls=-1.2, .scale=0.1, .depth=0, .eye=1.5, .sun=0.25, .sky=12, .star=11};
|
||||
embset eoutnih = embset{.name="out NIH", .se=geom3::seNIH, .walls=1.2, .scale=0.1, .depth=0, .eye=1.5, .sun=0.25, .sky=8, .star=7.5};
|
||||
embset eclifford = embset{.name="Clifford", .se=geom3::seCliffordTorus, .walls=1.2, .scale=M_PI/10, .depth=-0.0561826, .eye=1.5, .sun=0.25, .sky=2.55, .star=2.3};
|
||||
embset enil = embset{.name="Nil flat", .se=geom3::seNil, .walls=1.2, .scale=0.1, .depth=0, .eye=1.5, .sun=0.25, .sky=12, .star=11};
|
||||
embset esl2 = embset{.name="SL(2,R) flat", .se=geom3::seSL2, .walls=1.2, .scale=0.1, .depth=0, .eye=1.5, .sun=0.25, .sky=12, .star=11};
|
||||
embset eincylh = embset{.name="in cylinderH", .se=geom3::seCylinderH, .walls=1.2, .scale=M_PI/10, .depth=0, .eye=1.5, .sun=0.10472, .sky=2.6, .star=2.4};
|
||||
embset eincylhe = embset{.name="in cylinderHE", .se=geom3::seCylinderHE, .walls=1.2, .scale=M_PI/10, .depth=0, .eye=1.5, .sun=0.10472, .sky=2.6, .star=2.4};
|
||||
embset eincylnil = embset{.name="in cylinder Nil", .se=geom3::seCylinderNil, .walls=1.2, .scale=M_PI/10, .depth=0, .eye=1.5, .sun=0.10472, .sky=2.6, .star=2.4};
|
||||
embset eincylsl = embset{.name="in cylinder SL(2,R)", .se=geom3::seCylinderSL2, .walls=1.2, .scale=M_PI/10, .depth=0, .eye=1.5, .sun=0.10472, .sky=2.6, .star=2.4};
|
||||
embset einhorocyl = embset{.name="in horocylinder", .se=geom3::seCylinderHoro, .walls=-1.2, .scale=M_PI/10, .depth=0, .eye=1.5, .sun=0.10472, .sky=8, .star=7.5};
|
||||
embset eouthorocyl = embset{.name="out horocylinder", .se=geom3::seCylinderHoro, .walls=1.2, .scale=M_PI/10, .depth=0, .eye=1.5, .sun=0.10472, .sky=4, .star=3.5};
|
||||
embset eprodh_flat = embset{.name="hyperbolic product (flat)", .se=geom3::seProductH, .walls=1.2, .scale=M_PI/10, .depth=0, .eye=1.5, .sun=0.10472, .sky=2.6, .star=2.4};
|
||||
embset eprodh_concave = embset{.name="hyperbolic product (concave)", .se=geom3::seProductH, .walls=1.2, .scale=M_PI/10, .depth=1, .eye=1.5, .sun=0.10472, .sky=2.6, .star=2.4};
|
||||
embset eprods_flat = embset{.name="spherical product (flat)", .se=geom3::seProductS, .walls=1.2, .scale=M_PI/10, .depth=0, .eye=1.5, .sun=0.10472, .sky=2.6, .star=2.4};
|
||||
embset eprods_concave = embset{.name="spherical product (concave)", .se=geom3::seProductS, .walls=1.2, .scale=M_PI/10, .depth=0.8333, .eye=1.5, .sun=0.10472, .sky=2.6, .star=2.4};
|
||||
embset eincyl = embset("in cylinder E", geom3::seCylinderE, 1.2, M_PI/10, 0, 1.5, 0.10472, 2.6, 2.4);
|
||||
embset eoutcyl = embset("out cylinder E", geom3::seCylinderE, -1.2, M_PI/10, 0, 1.5, 0.3, 10, 9);
|
||||
embset eouthoro = embset("out horosphere", geom3::seLowerCurvature, 1.2, 0.1, 0, 1.5, 0.25, 8, 7.5);
|
||||
embset einhoro = embset("in horosphere", geom3::seLowerCurvature, -1.2, 0.1, 0, 1.5, 0.25, 12, 11);
|
||||
embset einhoro_small = embset("in horosphere (small sky)", geom3::seLowerCurvature, -1.2, 0.1, 0, 1.5, 0.25, 18, 17);
|
||||
embset esolv = embset("solv", geom3::seSol, 1.2, 0.1, 0, 1.5, 0.25, 12, 11);
|
||||
embset einnih = embset("in NIH", geom3::seNIH, -1.2, 0.1, 0, 1.5, 0.25, 12, 11);
|
||||
embset eoutnih = embset("out NIH", geom3::seNIH, 1.2, 0.1, 0, 1.5, 0.25, 8, 7.5);
|
||||
embset eclifford = embset("Clifford", geom3::seCliffordTorus, 1.2, M_PI/10, -0.0561826, 1.5, 0.25, 2.55, 2.3);
|
||||
embset enil = embset("Nil flat", geom3::seNil, 1.2, 0.1, 0, 1.5, 0.25, 12, 11);
|
||||
embset esl2 = embset("SL(2,R) flat", geom3::seSL2, 1.2, 0.1, 0, 1.5, 0.25, 12, 11);
|
||||
embset eincylh = embset("in cylinderH", geom3::seCylinderH, 1.2, M_PI/10, 0, 1.5, 0.10472, 2.6, 2.4);
|
||||
embset eincylhe = embset("in cylinderHE", geom3::seCylinderHE, 1.2, M_PI/10, 0, 1.5, 0.10472, 2.6, 2.4);
|
||||
embset eincylnil = embset("in cylinder Nil", geom3::seCylinderNil, 1.2, M_PI/10, 0, 1.5, 0.10472, 2.6, 2.4);
|
||||
embset eincylsl = embset("in cylinder SL(2,R)", geom3::seCylinderSL2, 1.2, M_PI/10, 0, 1.5, 0.10472, 2.6, 2.4);
|
||||
embset einhorocyl = embset("in horocylinder", geom3::seCylinderHoro, -1.2, M_PI/10, 0, 1.5, 0.10472, 8, 7.5);
|
||||
embset eouthorocyl = embset("out horocylinder", geom3::seCylinderHoro, 1.2, M_PI/10, 0, 1.5, 0.10472, 4, 3.5);
|
||||
embset eprodh_flat = embset("hyperbolic product (flat)", geom3::seProductH, 1.2, M_PI/10, 0, 1.5, 0.10472, 2.6, 2.4);
|
||||
embset eprodh_concave = embset("hyperbolic product (concave)", geom3::seProductH, 1.2, M_PI/10, 1, 1.5, 0.10472, 2.6, 2.4);
|
||||
embset eprods_flat = embset("spherical product (flat)", geom3::seProductS, 1.2, M_PI/10, 0, 1.5, 0.10472, 2.6, 2.4);
|
||||
embset eprods_concave = embset("spherical product (concave)", geom3::seProductS, 1.2, M_PI/10, 0.8333, 1.5, 0.10472, 2.6, 2.4);
|
||||
|
||||
embset& edok() { return vid.wall_height > 0 ? edefault : edefaulti; }
|
||||
|
||||
|
|
|
@ -325,6 +325,8 @@ bool view_labels = true, view_lines = true;
|
|||
|
||||
namespace hr {
|
||||
|
||||
extern ccolor::data grigorchuk_coloring;
|
||||
|
||||
struct hrmap_grigorchuk : hrmap_standard {
|
||||
|
||||
heptagon *origin;
|
||||
|
@ -411,8 +413,8 @@ struct hrmap_grigorchuk : hrmap_standard {
|
|||
|
||||
if(grigorchuk::view_labels) queuestr(V, 0.3, grigorchuk::deform(dec[c->master]), 0xFFFFFF);
|
||||
|
||||
if(patterns::whichCanvas == 'G' && c->landparam == 0)
|
||||
c->landparam = 0x102008 * (1 + ((hrmap_grigorchuk*)currentmap)->dec[c->master]->len);
|
||||
if(ccolor::which == &grigorchuk_coloring && c->landparam == 0)
|
||||
c->landparam = grigorchuk_coloring(c);
|
||||
|
||||
drawcell(c, V * currentmap->master_relative(c, false));
|
||||
|
||||
|
@ -436,6 +438,10 @@ struct hrmap_grigorchuk : hrmap_standard {
|
|||
|
||||
eGeometry gGrigorchuk(eGeometry(-1));
|
||||
|
||||
ccolor::data grigorchuk_coloring = ccolor::data("Grigorchuk", [] { return geometry == gGrigorchuk; }, [] (cell *c, ccolor::data& cco) {
|
||||
return 0x102008 * (1 + ((hrmap_grigorchuk*)currentmap)->dec[c->master]->len);
|
||||
}, {});
|
||||
|
||||
void create_grigorchuk_geometry() {
|
||||
if(gGrigorchuk != eGeometry(-1)) return;
|
||||
ginf.push_back(ginf[gNormal]);
|
||||
|
@ -449,6 +455,7 @@ void create_grigorchuk_geometry() {
|
|||
gi.menu_displayed_name = "Grigorchuk group";
|
||||
gi.shortname = "Grig";
|
||||
gi.default_variation = eVariation::pure;
|
||||
ccolor::all.push_back(&grigorchuk_coloring);
|
||||
}
|
||||
|
||||
int readArgsG() {
|
||||
|
@ -483,11 +490,6 @@ int readArgsG() {
|
|||
|
||||
auto hook = addHook(hooks_args, 100, readArgsG)
|
||||
+ addHook(hooks_newmap, 100, [] { return geometry == gGrigorchuk ? new hrmap_grigorchuk : nullptr; })
|
||||
+ addHook(patterns::hooks_generate_canvas, 100, [] (cell* c) {
|
||||
if(patterns::whichCanvas == 'G' && geometry == gGrigorchuk)
|
||||
return 0x102008 * (1 + ((hrmap_grigorchuk*)currentmap)->dec[c->master]->len);
|
||||
return -1;
|
||||
})
|
||||
+ addHook(dialog::hooks_display_dialog, 100, [] () {
|
||||
if(current_screen_cfunction() == showEuclideanMenu && geometry == gGrigorchuk) {
|
||||
dialog::addBoolItem_action(XLAT("Grigorchuk lines"), grigorchuk::view_lines, 'L');
|
||||
|
@ -516,7 +518,7 @@ auto hook = addHook(hooks_args, 100, readArgsG)
|
|||
if(mode == pmStart) {
|
||||
grigorchuk::grig_limit = 10000;
|
||||
gamestack::push();
|
||||
slide_backup(patterns::whichCanvas, 'G');
|
||||
slide_backup(ccolor::which, &grigorchuk_coloring);
|
||||
slide_backup(firstland, laCanvas);
|
||||
slide_backup(specialland, laCanvas);
|
||||
set_geometry(gGrigorchuk);
|
||||
|
|
|
@ -74,8 +74,7 @@ void run_cpick() {
|
|||
crystal::set_crystal(6);
|
||||
set_variation(eVariation::pure);
|
||||
enable_canvas();
|
||||
patterns::whichCanvas = 'g';
|
||||
patterns::canvasback = 0;
|
||||
ccolor::set_plain(0);
|
||||
check_cgi();
|
||||
start_game();
|
||||
current_center = currentmap->gamestart();
|
||||
|
@ -208,8 +207,7 @@ void run_sb() {
|
|||
crystal::set_crystal(6);
|
||||
set_variation(eVariation::pure);
|
||||
enable_canvas();
|
||||
patterns::whichCanvas = 'g';
|
||||
patterns::canvasback = 0;
|
||||
ccolor::set_plain(0);
|
||||
check_cgi();
|
||||
rv_hook(hooks_drawcell, 100, sokomap);
|
||||
start_game();
|
||||
|
@ -394,7 +392,7 @@ int mycanvas(cell *c) {
|
|||
}
|
||||
|
||||
void enable() {
|
||||
rv_hook(patterns::hooks_generate_canvas, 100, mycanvas);
|
||||
rv_hook(ccolor::hooks_generate_canvas, 100, mycanvas);
|
||||
}
|
||||
|
||||
auto explore_structure(int _shapeid) {
|
||||
|
@ -407,7 +405,7 @@ auto explore_structure(int _shapeid) {
|
|||
stop_game();
|
||||
set_geometry(geometry == gCrystal534 ? gCrystal534 : gCrystal344);
|
||||
enable_canvas();
|
||||
patterns::whichCanvas = ' ';
|
||||
ccolor::which = &ccolor::plain;
|
||||
shapeid = _shapeid;
|
||||
enable();
|
||||
crystal::crystal_period = 4;
|
||||
|
@ -444,7 +442,7 @@ void house(int sides, int shape = 10) {
|
|||
crystal::set_crystal(sides);
|
||||
set_variation(eVariation::pure);
|
||||
enable_canvas();
|
||||
patterns::whichCanvas = ' ';
|
||||
ccolor::which = &ccolor::plain;
|
||||
shapeid = shape;
|
||||
check_cgi();
|
||||
enable();
|
||||
|
@ -466,7 +464,7 @@ tour::slide *gen_high_demo() {
|
|||
sync(mode, VC);
|
||||
if(mode == pmStart) {
|
||||
crystal::set_crystal(6);
|
||||
patterns::whichCanvas = 'K';
|
||||
ccolor::which = &ccolor::crystal_colors;
|
||||
start_game();
|
||||
}
|
||||
}
|
||||
|
@ -479,7 +477,7 @@ tour::slide *gen_high_demo() {
|
|||
sync(mode, VC);
|
||||
if(mode == pmStart) {
|
||||
crystal::set_crystal(8);
|
||||
patterns::whichCanvas = 'K';
|
||||
ccolor::which = &ccolor::crystal_colors;
|
||||
start_game();
|
||||
}
|
||||
}
|
||||
|
@ -563,10 +561,7 @@ tour::slide *gen_high_demo() {
|
|||
sync(mode, NO_VC | PLAYER);
|
||||
if(mode == pmStart) {
|
||||
crystal::set_crystal(6);
|
||||
patterns::whichCanvas = 'c';
|
||||
colortables['c'][0] = 0x208020;
|
||||
colortables['c'][1] = 0x105010;
|
||||
patterns::canvasback = 0x101010;
|
||||
ccolor::set_colors(ccolor::chessboard, {0x208020, 0x105010});
|
||||
start_game();
|
||||
auto & us = vid.cs;
|
||||
us.charid = 4;
|
||||
|
|
|
@ -374,10 +374,8 @@ void enable() {
|
|||
|
||||
vid.linequality = 4;
|
||||
enable_canvas();
|
||||
patterns::whichCanvas = 'F';
|
||||
|
||||
colortables['F'][0] = 0x80C080;
|
||||
colortables['F'][1] = 0x80A080;
|
||||
ccolor::set_colors(ccolor::football, {0x80C080, 0x80A080});
|
||||
pconf.scale = .3;
|
||||
|
||||
vid.use_smart_range = 2;
|
||||
|
|
|
@ -246,7 +246,7 @@ vector<cell*> current_list;
|
|||
|
||||
void mine_slide(tour::presmode mode, reaction_t set_geom, function<vector<cell*>()> celllister, function<void(cell*)> assigner) {
|
||||
using namespace tour;
|
||||
patterns::canvasback = 0;
|
||||
ccolor::plain.ctab = {0};
|
||||
setCanvas(mode, '0');
|
||||
if(mode == pmStart) {
|
||||
slide_backup(mapeditor::drawplayer, false);
|
||||
|
@ -334,7 +334,7 @@ void enable_earth() {
|
|||
stop_game();
|
||||
set_geometry(gSphere);
|
||||
enable_canvas();
|
||||
patterns::whichCanvas = 'F';
|
||||
ccolor::which = &ccolor::football;
|
||||
start_game();
|
||||
texture::config.configname = "textures/earth.txc";
|
||||
texture::config.load();
|
||||
|
@ -543,8 +543,8 @@ slide sweeper_slides[] = {
|
|||
stop_game();
|
||||
set_geometry(g45);
|
||||
set_variation(eVariation::pure);
|
||||
tour::slide_backup(colortables['c'][0], 0x104010);
|
||||
tour::slide_backup(colortables['c'][1], 0x10F010);
|
||||
tour::slide_backup(ccolor::chessboard.ctab[0], 0x104010);
|
||||
tour::slide_backup(ccolor::chessboard.ctab[1], 0x10F010);
|
||||
tour::slide_backup(vid.use_smart_range, 2);
|
||||
tour::slide_backup(vid.smart_range_detail, 1);
|
||||
start_game();
|
||||
|
@ -562,7 +562,7 @@ slide sweeper_slides[] = {
|
|||
setCanvas(mode, 'g');
|
||||
non_game_slide_scroll(mode);
|
||||
if(mode == pmStart) {
|
||||
tour::slide_backup(patterns::canvasback, 0x10A010);
|
||||
tour::slide_backup(ccolor::plain.ctab[0], 0x10A010);
|
||||
stop_game();
|
||||
set_geometry(gBinary4);
|
||||
set_variation(eVariation::pure);
|
||||
|
@ -840,7 +840,7 @@ slide sweeper_slides[] = {
|
|||
setCanvas(mode, 'g');
|
||||
non_game_slide_scroll(mode);
|
||||
if(mode == pmStart) {
|
||||
tour::slide_backup(patterns::canvasback, 0x10A010);
|
||||
tour::slide_backup(ccolor::plain.ctab[0], 0x10A010);
|
||||
stop_game();
|
||||
set_geometry(gBinary4);
|
||||
set_variation(eVariation::pure);
|
||||
|
|
|
@ -217,8 +217,7 @@ void create_intra_solv() {
|
|||
}
|
||||
|
||||
void create_intra_120() {
|
||||
patterns::whichCanvas = 'r';
|
||||
patterns::rwalls = 0;
|
||||
ccolor::set_random(0);
|
||||
if(intra::in) intra::become();
|
||||
else stop_game();
|
||||
arcm::current.parse("8,4,6");
|
||||
|
@ -261,8 +260,7 @@ void create_intra_120() {
|
|||
}
|
||||
|
||||
void create_intra_1440() {
|
||||
patterns::whichCanvas = 'r';
|
||||
patterns::rwalls = 0;
|
||||
ccolor::set_random(0);
|
||||
if(intra::in) intra::become();
|
||||
else stop_game();
|
||||
set_geometry(gCell8);
|
||||
|
@ -330,8 +328,7 @@ vector<reaction_t> portals;
|
|||
|
||||
void create_intra_bxe() {
|
||||
println(hlog, "called create_intra_bxe");
|
||||
patterns::whichCanvas = 'r';
|
||||
patterns::rwalls = 100;
|
||||
ccolor::set_random(100);
|
||||
if(intra::in) intra::become();
|
||||
else stop_game();
|
||||
hybrid::csteps = 0;
|
||||
|
@ -404,8 +401,7 @@ void recurse_portal_solv2(int r, cell *cl, cell *cr) {
|
|||
|
||||
void create_intra_sol() {
|
||||
println(hlog, "called create_intra_sol");
|
||||
patterns::whichCanvas = 'r';
|
||||
patterns::rwalls = 100;
|
||||
ccolor::set_random(100);
|
||||
if(intra::in) intra::become();
|
||||
else stop_game();
|
||||
|
||||
|
@ -534,6 +530,12 @@ bool vr_keys(int sym, int uni) {
|
|||
|
||||
// all generators will add to the current scene
|
||||
|
||||
#if CAP_VR
|
||||
#define IF_VR(x) x
|
||||
#else
|
||||
#define IF_VR(x)
|
||||
#endif
|
||||
|
||||
auto hooks =
|
||||
// generate scene with H3, H2xE, E3, S2xE (8x6), S3 (16-cell) with floors; runs automatically
|
||||
arg::add3("-intra-floors", create_intra_floors)
|
||||
|
@ -574,11 +576,11 @@ auto hooks =
|
|||
mapstream::loadMap(s);
|
||||
slide_backup(ray::fixed_map, true);
|
||||
slide_backup(ray::max_iter_intra, y);
|
||||
#if CAP_VR
|
||||
IF_VR(
|
||||
slide_backup(vrhr::hsm, vrhr::eHeadset::holonomy);
|
||||
slide_backup(vrhr::eyes, vrhr::eEyes::truesim);
|
||||
slide_backup(vrhr::cscr, vrhr::eCompScreen::eyes);
|
||||
#endif
|
||||
)
|
||||
starter.clear();
|
||||
rogueviz::rv_hook(hooks_handleKey, 101, vr_keys);
|
||||
popScreenAll();
|
||||
|
@ -630,5 +632,6 @@ auto hooks =
|
|||
{loader{"run this visualization", 'r', load("solv-h3-scene.lev", 0.05, 3000)}});
|
||||
}));
|
||||
}
|
||||
#undef IF_VR
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -144,8 +144,7 @@ void magic(int sides) {
|
|||
crystal::set_crystal(sides);
|
||||
set_variation(eVariation::pure);
|
||||
enable_canvas();
|
||||
patterns::whichCanvas = 'g';
|
||||
patterns::canvasback = back;
|
||||
ccolor::set_plain(back);
|
||||
check_cgi();
|
||||
start_game();
|
||||
|
||||
|
|
|
@ -559,7 +559,7 @@ void pick_pattern() {
|
|||
dialog::add_action([] {
|
||||
chg_pattern([] {
|
||||
enable_canvas();
|
||||
patterns::whichCanvas = 'B';
|
||||
ccolor::which = &ccolor::sides;
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -570,7 +570,7 @@ void pick_pattern() {
|
|||
gp::param.second = 0;
|
||||
set_variation(eVariation::goldberg);
|
||||
enable_canvas();
|
||||
patterns::whichCanvas = 'F';
|
||||
ccolor::which = &ccolor::football;
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -579,7 +579,7 @@ void pick_pattern() {
|
|||
chg_pattern([] {
|
||||
set_geometry(gOctagon);
|
||||
enable_canvas();
|
||||
patterns::whichCanvas = 'T';
|
||||
ccolor::which = &ccolor::zebra_stripes;
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -612,7 +612,7 @@ void pick_pattern() {
|
|||
arcm::current.parse("4^5");
|
||||
set_geometry(gArchimedean);
|
||||
enable_canvas();
|
||||
patterns::whichCanvas = 'A';
|
||||
ccolor::which = &ccolor::shape;
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -26,10 +26,10 @@ auto geoslide(eGeometry g, char canvas, int jhole, int jblock) {
|
|||
tour::slide_backup<ld>(sightranges[gSol], 7);
|
||||
tour::slide_backup<ld>(sightranges[gSpace435], 7);
|
||||
vid.texture_step = 4;
|
||||
tour::slide_backup(patterns::jhole, jhole);
|
||||
tour::slide_backup(patterns::rwalls, jhole);
|
||||
tour::slide_backup(patterns::jblock, jblock);
|
||||
tour::slide_backup(patterns::whichCanvas, canvas);
|
||||
tour::slide_backup(ccolor::jhole, jhole);
|
||||
tour::slide_backup(ccolor::rwalls, jhole);
|
||||
tour::slide_backup(ccolor::jblock, jblock);
|
||||
tour::slide_backup(ccolor::which, ccolor::legacy(canvas));
|
||||
tour::slide_backup(vid.linewidth, vid.linewidth / 10);
|
||||
start_game();
|
||||
if(jblock < 0) {
|
||||
|
@ -45,7 +45,7 @@ auto geoslide(eGeometry g, char canvas, int jhole, int jblock) {
|
|||
if(in_special && among(mode, pmGeometrySpecial, pmStop)) {
|
||||
in_special = false;
|
||||
gamestack::pop();
|
||||
patterns::whichCanvas = canvas;
|
||||
ccolor::which = ccolor::legacy(canvas);
|
||||
vid.grid = false;
|
||||
fat_edges = false;
|
||||
sightranges[gSpace435] = 7;
|
||||
|
@ -54,7 +54,7 @@ auto geoslide(eGeometry g, char canvas, int jhole, int jblock) {
|
|||
else if(mode == pmGeometrySpecial && !in_special) {
|
||||
in_special = true;
|
||||
gamestack::push();
|
||||
patterns::whichCanvas = 'g';
|
||||
ccolor::set_plain(0);
|
||||
vid.grid = true;
|
||||
stdgridcolor = 0xFFFF00FF;
|
||||
fat_edges = true;
|
||||
|
|
|
@ -114,7 +114,7 @@ void run_snub(int v, int w) {
|
|||
check_cgi();
|
||||
cgi.require_basics();
|
||||
specialland = laCanvas;
|
||||
patterns::whichCanvas = 'A';
|
||||
ccolor::which = &ccolor::shape;
|
||||
// vid.wallmode = 1;
|
||||
printf("start game\n");
|
||||
printf("distlimit = %d\n", cgi.base_distlimit);
|
||||
|
|
|
@ -591,7 +591,7 @@ void enable_earth() {
|
|||
stop_game();
|
||||
set_geometry(gSphere);
|
||||
enable_canvas();
|
||||
patterns::whichCanvas = 'F';
|
||||
ccolor::which = &ccolor::football;
|
||||
start_game();
|
||||
texture::config.configname = "textures/earth.txc";
|
||||
texture::config.load();
|
||||
|
@ -635,8 +635,8 @@ slide dmv_slides[] = {
|
|||
set_geometry(gArchimedean); arcm::current.parse("3^6");
|
||||
set_variation(eVariation::pure);
|
||||
|
||||
slide_backup(colortables['F'][0], 0xC0FFC0);
|
||||
slide_backup(colortables['F'][1], 0x80FF80);
|
||||
slide_backup(ccolor::football.ctab[0], 0xC0FFC0);
|
||||
slide_backup(ccolor::football.ctab[1], 0x80FF80);
|
||||
slide_backup(pconf.alpha, 1);
|
||||
slide_backup(pconf.scale, 1);
|
||||
start_game();
|
||||
|
@ -708,8 +708,8 @@ slide dmv_slides[] = {
|
|||
slide_backup(specialland, laCanvas);
|
||||
set_geometry(gNormal);
|
||||
set_variation(eVariation::bitruncated);
|
||||
slide_backup(colortables['F'][0], 0xC0FFC0);
|
||||
slide_backup(colortables['F'][1], 0x80FF80);
|
||||
slide_backup(ccolor::football.ctab[0], 0xC0FFC0);
|
||||
slide_backup(ccolor::football.ctab[1], 0x80FF80);
|
||||
slide_backup(pconf.alpha, 1);
|
||||
slide_backup(pconf.scale, 1);
|
||||
slide_backup(rug::mouse_control_rug, true);
|
||||
|
@ -755,7 +755,7 @@ slide dmv_slides[] = {
|
|||
|
||||
[] (presmode mode) {
|
||||
if(mode == pmStart) {
|
||||
slide_backup(patterns::rwalls, 10);
|
||||
slide_backup(ccolor::rwalls, 10);
|
||||
slide_backup(vid.fov, 120);
|
||||
}
|
||||
|
||||
|
|
|
@ -190,6 +190,12 @@ int args() {
|
|||
return 0;
|
||||
}
|
||||
|
||||
#if CAP_RAY
|
||||
#define IF_RAY(x) x
|
||||
#else
|
||||
#define IF_RAY(x)
|
||||
#endif
|
||||
|
||||
auto hooks =
|
||||
addHook(hooks_args, 100, args)
|
||||
+ addHook_rvslides(180, [] (string s, vector<tour::slide>& v) {
|
||||
|
@ -214,10 +220,10 @@ auto hooks =
|
|||
set_geometry(gRotSpace);
|
||||
slide_backup(rots::underlying_scale, .25);
|
||||
slide_backup(qmode, m);
|
||||
#if CAP_RAY
|
||||
IF_RAY(
|
||||
slide_backup(ray::max_cells, 32768);
|
||||
slide_backup(ray::fixed_map, true);
|
||||
#endif
|
||||
)
|
||||
slide_backup(camera_speed, .1);
|
||||
enable();
|
||||
start_game();
|
||||
|
@ -240,11 +246,11 @@ auto hooks =
|
|||
set_geometry(gRotSpace);
|
||||
slide_backup(rots::underlying_scale, .25);
|
||||
slide_backup(qmode, m);
|
||||
#if CAP_RAY
|
||||
IF_RAY(
|
||||
slide_backup(ray::max_cells, 32768);
|
||||
slide_backup(ray::fixed_map, true);
|
||||
slide_backup(ray::want_use, 2);
|
||||
#endif
|
||||
)
|
||||
slide_backup(camera_speed, .1);
|
||||
enable();
|
||||
start_game();
|
||||
|
@ -256,6 +262,7 @@ auto hooks =
|
|||
}
|
||||
});
|
||||
|
||||
#undef IF_RAY
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -187,7 +187,7 @@ void reverb_queue() {
|
|||
int maxvol = 1;
|
||||
|
||||
/** draw bird, and also record the distance data about cell c */
|
||||
bool draw_bird(cell *c, const transmatrix& V) {
|
||||
bool draw_bird(cell *c, const shiftmatrix& V) {
|
||||
|
||||
if(!in) return false;
|
||||
|
||||
|
@ -211,8 +211,8 @@ bool draw_bird(cell *c, const transmatrix& V) {
|
|||
|
||||
auto& ci = infos[c];
|
||||
ci.curframe = frameid;
|
||||
ci.curdist[0] = hdist0(xpush(-iad) * tC0(V));
|
||||
ci.curdist[1] = hdist0(xpush(+iad) * tC0(V));
|
||||
ci.curdist[0] = hdist0(xpush(-iad) * tC0(V.T));
|
||||
ci.curdist[1] = hdist0(xpush(+iad) * tC0(V.T));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -221,7 +221,7 @@ static int isor;
|
|||
|
||||
void show() {
|
||||
cmode = sm::SIDE | sm::MAYDARK;
|
||||
gamescreen(0);
|
||||
gamescreen();
|
||||
dialog::init(XLAT("reverb"), 0xFFFFFFFF, 150, 0);
|
||||
|
||||
dialog::addSelItem("speed of sound", "1/" + fts(speed_of_sound), 's');
|
||||
|
@ -254,7 +254,8 @@ void show() {
|
|||
|
||||
dialog::add_action([]() {
|
||||
dialog::editNumber(isor, orig_size, orig_size*2, orig_size / 10, orig_size, "sample length", "warning: sample is cut off if you shorten it and then lengthen it again");
|
||||
dialog::reaction = [] {
|
||||
auto& ne = dialog::get_ne();
|
||||
ne.reaction = [] {
|
||||
orig.resize(isor);
|
||||
};
|
||||
});
|
||||
|
@ -293,11 +294,13 @@ auto hchook = addHook(hooks_drawcell, 100, draw_bird)
|
|||
|
||||
+ addHook(anims::hooks_anim, 100, [] {
|
||||
if(!auto_anim) return;
|
||||
if(cgi.cellshape.empty()) return;
|
||||
hyperpoint h1 = cgi.cellshape[0];
|
||||
hyperpoint h2 = normalize(cgi.cellshape[0] + cgi.cellshape[1]);
|
||||
auto& cs = currentmap->get_cellshape(cwt.at);
|
||||
auto vo = cs.vertices_only;
|
||||
if(vo.empty()) return;
|
||||
hyperpoint h1 = vo[0];
|
||||
hyperpoint h2 = normalize(vo[0] + vo[1]);
|
||||
hyperpoint wc = Hypc;
|
||||
for(int i=0; i<cgi.face; i++) wc += cgi.cellshape[i];
|
||||
for(int i=0; i<cgi.face; i++) wc += vo[i];
|
||||
hyperpoint h3 = normalize(wc);
|
||||
if(cgflags & qIDEAL) {
|
||||
println(hlog, "h1 was: ", h1);
|
||||
|
@ -383,8 +386,10 @@ auto hchook = addHook(hooks_drawcell, 100, draw_bird)
|
|||
patterns::rwalls = 100;
|
||||
mapeditor::drawplayer = false;
|
||||
start_game();
|
||||
if(!cgi.cellshape.empty())
|
||||
println(hlog, "edge = ", hdist(cgi.cellshape[0], cgi.cellshape[1]));
|
||||
auto& cs = currentmap->get_cellshape(cwt.at);
|
||||
auto& vo = cs.vertices_only;
|
||||
if(!vo.empty())
|
||||
println(hlog, "edge = ", hdist(vo[0], vo[1]));
|
||||
/* Doppler effect is weird if scrolling if not smooth */
|
||||
smooth_scrolling = true;
|
||||
/* disable the frustum culling (we need sound from every direction) */
|
||||
|
|
|
@ -108,7 +108,7 @@ bool labeller(cell* c, const shiftmatrix& V) {
|
|||
if(m) {
|
||||
string s = m->asg[c->master].second;
|
||||
cgi.scalefactor = 1;
|
||||
queuestr(V, 0.5, s, colortables['j'][c->master->distance+1]);
|
||||
queuestr(V, 0.5, s, ccolor::jmap.ctab[c->master->distance+1]);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -179,7 +179,7 @@ namespace rogueviz {
|
|||
template<class T, class U> function<void(presmode)> roguevizslide(char c, const T& t, const U& f) {
|
||||
return [c,t,f] (presmode mode) {
|
||||
f(mode);
|
||||
patterns::canvasback = 0x101010;
|
||||
ccolor::plain.ctab = {0x101010};
|
||||
setCanvas(mode, c);
|
||||
if(mode == 1 || mode == pmGeometryStart) t();
|
||||
|
||||
|
@ -201,7 +201,7 @@ template<class T> function<void(presmode)> roguevizslide(char c, const T& t) { r
|
|||
template<class T, class U>
|
||||
function<void(presmode)> roguevizslide_action(char c, const T& t, const U& act) {
|
||||
return [c,t,act] (presmode mode) {
|
||||
patterns::canvasback = 0x101010;
|
||||
ccolor::plain.ctab = {0x101010};
|
||||
setCanvas(mode, c);
|
||||
if(mode == pmStart || mode == pmGeometryStart) t();
|
||||
|
||||
|
@ -342,6 +342,8 @@ namespace objmodels {
|
|||
virtual void process_triangle(vector<hyperpoint>& hys, vector<hyperpoint>& tot, bool textured, object *co);
|
||||
|
||||
bool available();
|
||||
|
||||
virtual ~model() {}
|
||||
};
|
||||
|
||||
void add_model_settings();
|
||||
|
|
|
@ -431,7 +431,7 @@ namespace sag {
|
|||
|
||||
if(t2 - tl > 980) {
|
||||
tl = t2;
|
||||
println(hlog, hr::format("it %12Ld temp %6.4f [1/e at %13.6f] cost = %f ",
|
||||
println(hlog, hr::format("it %12lld temp %6.4f [1/e at %13.6f] cost = %f ",
|
||||
numiter, double(sag::temperature), (double) exp(sag::temperature),
|
||||
double(sag::cost)));
|
||||
}
|
||||
|
@ -458,7 +458,7 @@ namespace sag {
|
|||
auto t2 = SDL_GetTicks();
|
||||
if(t2 - t1 > 1000) {
|
||||
t1 = t2;
|
||||
println(hlog, hr::format("it %12Ld temp %6.4f [1/e at %13.6f] cost = %f ",
|
||||
println(hlog, hr::format("it %12lld temp %6.4f [1/e at %13.6f] cost = %f ",
|
||||
numiter, double(sag::temperature), (double) exp(sag::temperature),
|
||||
double(sag::cost)));
|
||||
}
|
||||
|
@ -491,7 +491,7 @@ namespace sag {
|
|||
if(t < (sag_ittime+1) / 2) ipturn *= 2;
|
||||
else if(t > sag_ittime * 2) ipturn /= 2;
|
||||
else ipturn = ipturn * sag_ittime / t;
|
||||
print(hlog, hr::format("it %12Ld temp %6.4f [2:%8.6f,10:%8.6f,50:%8.6f] cost = %f\n",
|
||||
print(hlog, hr::format("it %12lld temp %6.4f [2:%8.6f,10:%8.6f,50:%8.6f] cost = %f\n",
|
||||
numiter, double(sag::temperature),
|
||||
(double) exp(-2 * exp(-sag::temperature)),
|
||||
(double) exp(-10 * exp(-sag::temperature)),
|
||||
|
@ -734,7 +734,7 @@ namespace sag {
|
|||
|
||||
hyperpoint np = rgpushxto0(placement[i]) * h;
|
||||
|
||||
ld change;
|
||||
ld change = 0;
|
||||
for(auto e: edges_yes[i]) change -= lgemb.lyes(pdist(placement[i], placement[e]));
|
||||
for(auto e: edges_no[i]) change -= lgemb.lno(pdist(placement[i], placement[e]));
|
||||
for(auto e: edges_yes[i]) change += lgemb.lyes(pdist(np, placement[e]));
|
||||
|
@ -1097,7 +1097,7 @@ namespace sag {
|
|||
create_viz();
|
||||
|
||||
for(int i=0; i<DN; i++) {
|
||||
color_t col = patterns::compute_cell_color(sagcells[sagid[i]]);
|
||||
color_t col = ccolor::formula.f(sagcells[sagid[i]], ccolor::formula);
|
||||
col <<= 8;
|
||||
col |= 0xFF;
|
||||
vdata[i].cp.color1 = vdata[i].cp.color2 = col;
|
||||
|
|
|
@ -314,6 +314,12 @@ auto hchook = addHook(hooks_drawcell, 100, draw_snow)
|
|||
param_b(snow_not_player, "snow_not_player");
|
||||
})
|
||||
|
||||
#if CAP_SOLV
|
||||
#define IF_SOLV(x) x
|
||||
#else
|
||||
#define IF_SOLV(x)
|
||||
#endif
|
||||
|
||||
#if CAP_RVSLIDES
|
||||
+ addHook_rvslides(161, [] (string s, vector<tour::slide>& v) {
|
||||
if(s != "noniso") return;
|
||||
|
@ -381,16 +387,16 @@ auto hchook = addHook(hooks_drawcell, 100, draw_snow)
|
|||
set_geometry(gRotSpace);
|
||||
snow_lambda = 5;
|
||||
});
|
||||
#if CAP_SOLV
|
||||
snow_slide(v, "Solv", "Solv geometry. Like the non-isotropic hyperbolic geometry but where the horizontal and vertical curvatures work in the other way.", [] {
|
||||
IF_SOLV(snow_slide(v, "Solv", "Solv geometry. Like the non-isotropic hyperbolic geometry but where the horizontal and vertical curvatures work in the other way.", [] {
|
||||
set_geometry(gSol);
|
||||
// tour::slide_backup(snow_shape, 2);
|
||||
snow_lambda = 3;
|
||||
});
|
||||
#endif
|
||||
});)
|
||||
})
|
||||
#endif
|
||||
+ 0;
|
||||
|
||||
#undef IF_SOLV
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -149,7 +149,7 @@ ld evaluate_measure(manidata& emb, manidata& orig, vector<int>& mapp, vector<pai
|
|||
|
||||
}
|
||||
|
||||
static constexpr string som_test_dir = "results/";
|
||||
static const string som_test_dir = "results/";
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -85,6 +85,9 @@ static constexpr flagtype w_less_smart_advance = Flag(23); /*< stop early when e
|
|||
static constexpr flagtype w_no_queued_extensions = Flag(24); /*< consider extensions one by one */
|
||||
static constexpr flagtype w_no_branch_skipping = Flag(24); /*< do not skip branches */
|
||||
|
||||
/* extra */
|
||||
static constexpr flagtype w_optimize2 = Flag(25); /*< optimize in 2D */
|
||||
|
||||
/* for 3D honeycombs */
|
||||
static constexpr flagtype w_skip_transducers = Flag(32); /*< skip the transducer test */
|
||||
static constexpr flagtype w_skip_transducer_loops = Flag(33); /*< skip loops during the transducer test */
|
||||
|
@ -1563,6 +1566,7 @@ void minimize_rules() {
|
|||
int new_ids = 0;
|
||||
|
||||
for(int id=0; id<next_id; id++) {
|
||||
if(treestates[id].giver.at == nullptr) { new_id[id] = new_ids++; println(hlog, "no giver in minimize_rules for state ", id); continue; }
|
||||
auto aid = get_aid(treestates[id].giver);
|
||||
|
||||
if(!new_id_of.count(aid)) new_id_of[aid] = new_ids++;
|
||||
|
@ -2001,6 +2005,8 @@ EX void rules_iteration() {
|
|||
if(examine_branch(id, fb, sb)) checks_to_skip.insert(b);
|
||||
};
|
||||
|
||||
if(WDIM == 2 && (flags & w_optimize2)) optimize();
|
||||
|
||||
if(WDIM == 2) for(int id=0; id<isize(treestates); id++) if(treestates[id].is_live) {
|
||||
auto r = treestates[id].rules; /* no & because treestates might have moved */
|
||||
if(r.empty()) continue;
|
||||
|
|
|
@ -1430,7 +1430,7 @@ EX void optimize() {
|
|||
|
||||
int N = isize(treestates);
|
||||
|
||||
println(hlog, "optimize: changes = ", changes, " errors = ", errors, " unreachable = ", N - isize(seen));
|
||||
if(rdebug_flags & 64) println(hlog, "optimize: changes = ", changes, " errors = ", errors, " unreachable = ", N - isize(seen));
|
||||
|
||||
if(errors) throw rulegen_retry("error found in optimize");
|
||||
|
||||
|
@ -1471,7 +1471,7 @@ EX void optimize() {
|
|||
}
|
||||
}
|
||||
|
||||
if(steps) { println(hlog, "steps = ", steps); throw rulegen_retry("unreachable found in optimize"); }
|
||||
if(steps) { if(rdebug_flags & 64) println(hlog, "steps = ", steps); throw rulegen_retry("unreachable found in optimize"); }
|
||||
|
||||
important.clear();
|
||||
for(auto s: seen) important.push_back(treestates[s].giver);
|
||||
|
|
81
scores.cpp
81
scores.cpp
|
@ -22,12 +22,16 @@ string csub(const string& str, int q) {
|
|||
return str.substr(0, i);
|
||||
}
|
||||
|
||||
vector<int> column_width(POSSCORE+1, 4);
|
||||
|
||||
int colwidth(int scoredisplay) {
|
||||
if(scoredisplay == 0) return 5;
|
||||
return column_width[scoredisplay];
|
||||
/* if(scoredisplay == 0) return 5;
|
||||
if(scoredisplay == 1) return 16;
|
||||
if(scoredisplay == 5) return 8;
|
||||
if(scoredisplay == POSSCORE) return 8;
|
||||
return 4;
|
||||
if(scoredisplay == 68) return yasc_width;
|
||||
return 4; */
|
||||
}
|
||||
|
||||
bool isHardcore(score *S) {
|
||||
|
@ -91,6 +95,7 @@ string displayfor(int scoredisplay, score* S, bool shorten = false) {
|
|||
if(scoredisplay == 67) return XLAT("cheats");
|
||||
if(scoredisplay == 66) return XLAT("saves");
|
||||
if(scoredisplay == 197) return XLAT("players");
|
||||
if(scoredisplay == 68) return XLAT("where");
|
||||
return csub(str, 5);
|
||||
}
|
||||
if(scoredisplay == 0 || scoredisplay == 65) {
|
||||
|
@ -103,6 +108,11 @@ string displayfor(int scoredisplay, score* S, bool shorten = false) {
|
|||
return buf;
|
||||
}
|
||||
if(scoredisplay == POSSCORE) return modedesc(S);
|
||||
if(scoredisplay == 68) {
|
||||
eLand which = eLand(S->box[68]);
|
||||
if(which >= landtypes || which < 0) return "fail";
|
||||
return S->yasc_message + XLAT(" in %the1", which);
|
||||
}
|
||||
if(scoredisplay == 1) {
|
||||
time_t tim = S->box[1];
|
||||
char buf[128]; strftime(buf, 128, "%c", localtime(&tim));
|
||||
|
@ -162,27 +172,39 @@ void showPickScores() {
|
|||
};
|
||||
}
|
||||
|
||||
int scale = 2;
|
||||
|
||||
void show() {
|
||||
|
||||
if(columns.size() == 0) {
|
||||
columns.push_back(POSSCORE);
|
||||
for(int i=0; i<POSSCORE; i++) columns.push_back(i);
|
||||
for(int i=0; i<POSSCORE; i++) {
|
||||
if(i == 5) columns.push_back(68);
|
||||
else if(i == 68) columns.push_back(5);
|
||||
else columns.push_back(i);
|
||||
}
|
||||
}
|
||||
int y = vid.fsize * 5/2;
|
||||
int bx = vid.fsize;
|
||||
int score_size = vid.fsize / scale;
|
||||
int y = score_size * 5/2;
|
||||
int bx = score_size;
|
||||
getcstat = 0;
|
||||
|
||||
displaystr(bx*4, vid.fsize, 0, vid.fsize, "#", forecolor, 16);
|
||||
displaystr(bx*8, vid.fsize, 0, vid.fsize, XLAT("ver"), forecolor, 16);
|
||||
displaystr(bx*4, score_size, 0, vid.fsize, "#", forecolor, 16);
|
||||
displaystr(bx*8, score_size, 0, vid.fsize, XLAT("ver"), forecolor, 16);
|
||||
|
||||
int at = 9;
|
||||
for(int i=0; i<=POSSCORE; i++) {
|
||||
int c = columns[i];
|
||||
if(bx*at > vid.xres) break;
|
||||
if(displaystr(bx*at, vid.fsize, 0, vid.fsize, displayfor(c, NULL, true), i == curcol ? 0xFFD500 : forecolor, 0))
|
||||
string s = displayfor(c, NULL, true);
|
||||
auto& cw = column_width[c];
|
||||
cw = max(cw, textwidth(score_size, s) / bx + 1);
|
||||
if(displaystr(bx*at, score_size, 0, score_size, s, i == curcol ? 0xFFD500 : forecolor, 0))
|
||||
getcstat = 1000+i;
|
||||
at += colwidth(c);
|
||||
}
|
||||
|
||||
vector<int> next_column_width(POSSCORE+1, 0);
|
||||
|
||||
if(scorefrom < 0) scorefrom = 0;
|
||||
int id = 0;
|
||||
|
@ -205,28 +227,40 @@ void show() {
|
|||
|
||||
|
||||
rank++;
|
||||
displaystr(bx*4, y, 0, vid.fsize, its(rank), col, 16);
|
||||
displaystr(bx*4, y, 0, score_size, its(rank), col, 16);
|
||||
|
||||
displaystr(bx*8, y, 0, vid.fsize, S.ver, col, 16);
|
||||
displaystr(bx*8, y, 0, score_size, S.ver, col, 16);
|
||||
|
||||
int at = 9;
|
||||
for(int i=0; i<=POSSCORE; i++) {
|
||||
int c = columns[i];
|
||||
if(bx*at > vid.xres) break;
|
||||
at += colwidth(c);
|
||||
if(displaystr(bx*(at-1), y, 0, vid.fsize, displayfor(c, &S), col, 16))
|
||||
getcstat = 1000+i;
|
||||
string s = displayfor(c, &S);
|
||||
auto& ncw = next_column_width[c];
|
||||
ncw = max(ncw, textwidth(score_size, s) / bx + 1);
|
||||
if(c == 68) {
|
||||
if(displaystr(bx*at, y, 0, score_size, s, col, 0))
|
||||
getcstat = 1000+i;
|
||||
at += colwidth(c);
|
||||
}
|
||||
else {
|
||||
at += colwidth(c);
|
||||
if(displaystr(bx*(at-1), y, 0, score_size, s, col, 16))
|
||||
getcstat = 1000+i;
|
||||
}
|
||||
}
|
||||
|
||||
y += vid.fsize*5/4; id++;
|
||||
y += score_size*5/4; id++;
|
||||
}
|
||||
|
||||
column_width = next_column_width;
|
||||
int i0 = vid.yres - vid.fsize;
|
||||
int xr = vid.xres / 80;
|
||||
|
||||
displayButton(xr*10, i0, IFM("s - ") + XLAT("sort"), 's', 8);
|
||||
displayButton(xr*30, i0, IFM("t - ") + XLAT("choose"), 't', 8);
|
||||
displayButton(xr*50, i0, IFM(dialog::keyname(SDLK_ESCAPE) + " - ") + XLAT("go back"), '0', 8);
|
||||
displayButton(xr*50, i0, IFM("z - ") + XLAT("zoom"), 'z', 8);
|
||||
displayButton(xr*70, i0, IFM(dialog::keyname(SDLK_ESCAPE) + " - ") + XLAT("go back"), '0', 8);
|
||||
|
||||
keyhandler = [] (int sym, int uni) {
|
||||
if(DKEY == SDLK_LEFT || uni == 'h' || uni == 'a') {
|
||||
|
@ -246,6 +280,7 @@ void show() {
|
|||
scorefrom -= 5;
|
||||
else if(DKEY == SDLK_DOWN || uni == 'j' || uni == 'x')
|
||||
scorefrom += 5;
|
||||
else if(uni == 'z') scale = 3 - scale;
|
||||
else if(sym == PSEUDOKEY_WHEELUP)
|
||||
scorefrom--;
|
||||
else if(sym == PSEUDOKEY_WHEELDOWN)
|
||||
|
@ -289,9 +324,11 @@ void load() {
|
|||
addMessage(s0 + "Could not open the score file: " + scorefile);
|
||||
return;
|
||||
}
|
||||
string *yasc = nullptr;
|
||||
while(!feof(f)) {
|
||||
char buf[120];
|
||||
if(fgets(buf, 120, f) == NULL) break;
|
||||
const int buflen = 1200;
|
||||
char buf[buflen];
|
||||
if(fgets(buf, buflen, f) == NULL) break;
|
||||
if(buf[0] == 'H' && buf[1] == 'y') {
|
||||
score sc; bool ok = true;
|
||||
sc.box[MAXBOX-1] = 0;
|
||||
|
@ -320,7 +357,14 @@ void load() {
|
|||
if(sc.box[2] == 0) continue; // do not list zero scores
|
||||
sc.box[POSSCORE] = modediff(&sc);
|
||||
|
||||
if(ok && boxid > 20) scores.push_back(sc);
|
||||
if(ok && boxid > 20) {
|
||||
scores.push_back(sc);
|
||||
yasc = &scores.back().yasc_message;
|
||||
}
|
||||
}
|
||||
if(buf[0] == 'Y' && buf[1] == 'A' && buf[2] == 'S' && buf[3] == 'C' && buf[4] == ' ') {
|
||||
for(int i=5; i<buflen; i++) if(buf[i] == '\n' || buf[i] == '\r') buf[i] = 0;
|
||||
*yasc = buf+5;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -329,6 +373,7 @@ void load() {
|
|||
for(int i=0; i<POSSCORE; i++) sc.box[i] = save.box[i];
|
||||
sc.box[POSSCORE] = 0;
|
||||
sc.box[MAXBOX-1] = 1; sc.ver = "NOW";
|
||||
sc.yasc_message = canmove ? "on the run" : yasc_message;
|
||||
scores.push_back(sc);
|
||||
|
||||
fclose(f);
|
||||
|
|
31
shmup.cpp
31
shmup.cpp
|
@ -263,6 +263,7 @@ void killMonster(monster* m, eMonster who_kills, flagtype flags = 0) {
|
|||
if(m->dead) return;
|
||||
m->dead = true;
|
||||
if(isPlayer(m) && m->fragoff < curtime) {
|
||||
yasc_message = XLAT("killed by %the1", who_kills);
|
||||
if(multi::cpid == m->pid)
|
||||
multi::suicides[multi::cpid]++;
|
||||
else if(multi::cpid >= 0)
|
||||
|
@ -439,8 +440,10 @@ void shootBullet(monster *m) {
|
|||
}
|
||||
|
||||
EX void killThePlayer(eMonster m) {
|
||||
if(cpid >= 0 && cpid < MAXPLAYER && pc[cpid])
|
||||
if(cpid >= 0 && cpid < MAXPLAYER && pc[cpid]) {
|
||||
yasc_message = XLAT("killed by %the1", m);
|
||||
pc[cpid]->dead = true;
|
||||
}
|
||||
}
|
||||
|
||||
monster *playerCrash(monster *who, shiftpoint where) {
|
||||
|
@ -1148,7 +1151,7 @@ void movePlayer(monster *m, int delta) {
|
|||
}
|
||||
else if(
|
||||
(blown ? !passable(c2, m->base, P_ISPLAYER | P_BLOW) : !passable(c2, m->base, P_ISPLAYER | P_MIRROR | reflectflag)) &&
|
||||
!(isWatery(c2) && m->inBoat && !nonAdjacent(m->base,c2)))
|
||||
!(isWatery(c2) && m->inBoat && (!nonAdjacent(m->base,c2) || markOrb(itOrb37))))
|
||||
go = false;
|
||||
|
||||
}
|
||||
|
@ -1238,6 +1241,7 @@ void movePlayer(monster *m, int delta) {
|
|||
|
||||
if(c2->wall == waMineMine && !markOrb(itOrbAether) && !markOrb(itOrbWinter)) {
|
||||
items[itOrbLife] = 0;
|
||||
if(!m->dead) yasc_message = XLAT("stepped on a mine");
|
||||
m->dead = true;
|
||||
}
|
||||
#if CAP_COMPLEX2
|
||||
|
@ -1283,14 +1287,25 @@ void movePlayer(monster *m, int delta) {
|
|||
}
|
||||
|
||||
if(!markOrb(itOrbAether)) {
|
||||
if(m->base->wall == waChasm || m->base->wall == waClosedGate)
|
||||
if(m->base->wall == waChasm) {
|
||||
if(!m->dead) yasc_message = XLAT("fell into %the1", m->base->wall);
|
||||
m->dead = true;
|
||||
}
|
||||
|
||||
if(isWatery(m->base) && !m->inBoat && !markOrb(itOrbFish))
|
||||
if(m->base->wall == waClosedGate) {
|
||||
if(!m->dead) yasc_message = XLAT("killed by %the1", m->base->wall);
|
||||
m->dead = true;
|
||||
}
|
||||
|
||||
if(isFireOrMagma(m->base) && !markOrb(itOrbWinter))
|
||||
if(isWatery(m->base) && !m->inBoat && !markOrb(itOrbFish)) {
|
||||
if(!m->dead) yasc_message = XLAT("drowned in %the1", m->base->wall);
|
||||
m->dead = true;
|
||||
}
|
||||
|
||||
if(isFireOrMagma(m->base) && !markOrb(itOrbWinter)) {
|
||||
if(!m->dead) yasc_message = XLAT("burnt in %the1", m->base->wall);
|
||||
m->dead = true;
|
||||
}
|
||||
}
|
||||
|
||||
landvisited[m->base->land] = true;
|
||||
|
@ -2250,8 +2265,10 @@ void moveMonster(monster *m, int delta) {
|
|||
|
||||
if(!peace::on)
|
||||
for(int i=0; i<players; i++)
|
||||
if(crashintomon == pc[i])
|
||||
if(crashintomon == pc[i]) {
|
||||
yasc_message = XLAT("killed by %the1", m->type);
|
||||
pc[i]->dead = true;
|
||||
}
|
||||
|
||||
if(peace::on) ;
|
||||
|
||||
|
@ -2573,7 +2590,7 @@ EX void turn(int delta) {
|
|||
lmousetarget = mousetarget;
|
||||
|
||||
if(!shmup::on) return;
|
||||
if(!(cmode & sm::NORMAL)) {
|
||||
if(!(cmode & sm::NORMAL) || outoffocus) {
|
||||
#if CAP_RACING
|
||||
if(!in_pause) {
|
||||
in_pause = true;
|
||||
|
|
|
@ -178,6 +178,7 @@ struct hrmap_spherical : hrmap_standard {
|
|||
}
|
||||
|
||||
transmatrix relative_matrixc(cell *c2, cell *c1, const hyperpoint& hint) override {
|
||||
if(IRREGULAR) return relative_matrix_via_masters(c2, c1, hint);
|
||||
transmatrix T = iso_inverse(get_where(c1)) * get_where(c2);
|
||||
if(elliptic) fixelliptic(T);
|
||||
return T;
|
||||
|
|
424
system.cpp
424
system.cpp
File diff suppressed because it is too large
Load Diff
|
@ -1329,14 +1329,13 @@ EX void showMenu() {
|
|||
|
||||
dialog::addBoolItem(XLATN("Canvas"), specialland == laCanvas, 'X');
|
||||
dialog::add_action([] () {
|
||||
bool inwhite = specialland == laCanvas && patterns::whichCanvas == 'g' && patterns::canvasback == 0xFFFFFF;
|
||||
bool inwhite = specialland == laCanvas && ccolor::which == &ccolor::plain && ccolor::plain.ctab.size() == 1 && ccolor::plain.ctab[0] == 0xFFFFFF;
|
||||
if(inwhite)
|
||||
pushScreen(patterns::showPrePattern);
|
||||
else {
|
||||
stop_game();
|
||||
enable_canvas();
|
||||
patterns::whichCanvas = 'g';
|
||||
patterns::canvasback = 0xFFFFFF;
|
||||
ccolor::set_plain(0xFFFFFF);
|
||||
start_game();
|
||||
}
|
||||
});
|
||||
|
|
18
tour.cpp
18
tour.cpp
|
@ -110,8 +110,8 @@ EX void slide_action(presmode mode, char key, string text, reaction_t act) {
|
|||
help_extensions.push_back(help_extension{key, text, act});
|
||||
}
|
||||
|
||||
EX void enable_canvas_backup(char canv) {
|
||||
slide_backup(patterns::whichCanvas, canv);
|
||||
EX void enable_canvas_backup(ccolor::data *canv) {
|
||||
slide_backup(ccolor::which, canv);
|
||||
slide_backup(firstland, laCanvas);
|
||||
slide_backup(specialland, laCanvas);
|
||||
slide_backup(land_structure);
|
||||
|
@ -120,7 +120,7 @@ EX void enable_canvas_backup(char canv) {
|
|||
}
|
||||
|
||||
/** \brief an auxiliary function to enable a visualization in the Canvas land */
|
||||
EX void setCanvas(presmode mode, char canv) {
|
||||
EX void setCanvas(presmode mode, ccolor::data *canv) {
|
||||
if(mode == pmStart) {
|
||||
gamestack::push();
|
||||
enable_canvas_backup(canv);
|
||||
|
@ -133,6 +133,10 @@ EX void setCanvas(presmode mode, char canv) {
|
|||
}
|
||||
}
|
||||
|
||||
EX void setCanvas(presmode mode, char c) {
|
||||
setCanvas(mode, ccolor::legacy(c));
|
||||
}
|
||||
|
||||
/** \brief static mode: we get Orbs of Teleport to use them instead of movement */
|
||||
bool sickmode;
|
||||
|
||||
|
@ -638,7 +642,7 @@ EX slide default_slides[] = {
|
|||
"The world of HyperRogue is tiled with hexagons "
|
||||
"and heptagons; heptagons give extra space!\n\n",
|
||||
[] (presmode mode) {
|
||||
setCanvas(mode, 'F');
|
||||
setCanvas(mode, &ccolor::football);
|
||||
if(mode == 5) {
|
||||
cwt.at->move(0)->monst = moRunDog;
|
||||
cwt.at->move(1)->monst = moGoblin;
|
||||
|
@ -700,7 +704,7 @@ EX slide default_slides[] = {
|
|||
"running away in a straight line. "
|
||||
"Press '2' to try the same in the Euclidean world -- it is impossible.",
|
||||
[] (presmode mode) {
|
||||
setCanvas(mode, 'F');
|
||||
setCanvas(mode, &ccolor::football);
|
||||
if(mode == 5) {
|
||||
cwt.at->move(0)->monst = moRunDog;
|
||||
cwt.at->move(1)->monst = moGoblin;
|
||||
|
@ -861,7 +865,7 @@ EX slide default_slides[] = {
|
|||
"Hyperbolic geometry yields much more interesting periodic patterns "
|
||||
"than Euclidean.",
|
||||
[] (presmode mode) {
|
||||
setCanvas(mode, 't');
|
||||
setCanvas(mode, &ccolor::zebra_stripes);
|
||||
if(mode == 1)
|
||||
patterns::displaycodes = true,
|
||||
patterns::whichPattern = patterns::PAT_ZEBRA;
|
||||
|
@ -895,7 +899,7 @@ EX slide default_slides[] = {
|
|||
"On the following slide, the colors change smoothly in the whole infinite world. "
|
||||
"Again, this works better than in Euclidean geometry.",
|
||||
[] (presmode mode) {
|
||||
setCanvas(mode, 'l');
|
||||
setCanvas(mode, &ccolor::landscape);
|
||||
SHOWLAND ( l == laCanvas );
|
||||
}
|
||||
},
|
||||
|
|
113
yendor.cpp
113
yendor.cpp
|
@ -122,7 +122,7 @@ EX namespace yendor {
|
|||
|
||||
int tscorelast;
|
||||
|
||||
void uploadScore() {
|
||||
EX void uploadScore() {
|
||||
int tscore = 0;
|
||||
for(int i=1; i<YENDORLEVELS; i++)
|
||||
if(bestscore[0][i]) tscore += 999 + bestscore[0][i];
|
||||
|
@ -278,10 +278,12 @@ EX namespace yendor {
|
|||
goto retry;
|
||||
}
|
||||
|
||||
auto rollbacks = std::move(changes.rollbacks);
|
||||
for(int i=-1; i<key->type; i++) {
|
||||
cell *c2 = i >= 0 ? key->move(i) : key;
|
||||
checkTide(c2);
|
||||
c2->monst = moNone; c2->item = itNone;
|
||||
makeNoMonster(c2);
|
||||
c2->item = itNone;
|
||||
if(!passable(c2, NULL, P_MIRROR | P_MONSTER)) {
|
||||
if(c2->wall == waCavewall) c2->wall = waCavefloor;
|
||||
else if(c2->wall == waDeadwall) c2->wall = waDeadfloor2;
|
||||
|
@ -311,6 +313,7 @@ EX namespace yendor {
|
|||
if(c2->land == laMirrorWall && i == -1)
|
||||
c2->wall = waNone;
|
||||
}
|
||||
changes.rollbacks = std::move(rollbacks);
|
||||
key->item = itKey;
|
||||
|
||||
bool split_found = false;
|
||||
|
@ -760,18 +763,18 @@ EX namespace tactic {
|
|||
if(csum > recordsum[xc][land]) recordsum[xc][land] = csum;
|
||||
}
|
||||
|
||||
void record() {
|
||||
EX void record() {
|
||||
record(lasttactic, items[treasureType(lasttactic)]);
|
||||
}
|
||||
|
||||
void unrecord(eLand land, flagtype xc = modecode()) {
|
||||
EX void unrecord(eLand land, flagtype xc IS(modecode())) {
|
||||
if(land >=0 && land < landtypes) {
|
||||
for(int i=0; i<MAXTAC-1; i++) lsc[xc][land][i] = lsc[xc][land][i+1];
|
||||
lsc[xc][land][MAXTAC-1] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void unrecord() {
|
||||
EX void unrecord() {
|
||||
unrecord(lasttactic);
|
||||
}
|
||||
|
||||
|
@ -792,7 +795,7 @@ EX namespace tactic {
|
|||
achievement_score(lb, tscore);
|
||||
}
|
||||
|
||||
void uploadScore() {
|
||||
EX void uploadScore() {
|
||||
uploadScoreCode(0, LB_PURE_TACTICS);
|
||||
uploadScoreCode(2, LB_PURE_TACTICS_SHMUP);
|
||||
uploadScoreCode(4, LB_PURE_TACTICS_COOP);
|
||||
|
@ -959,7 +962,7 @@ EX map<modecode_t, string> meaning;
|
|||
|
||||
char xcheat;
|
||||
|
||||
void save_mode_data(hstream& f) {
|
||||
EX void save_mode_data(hstream& f) {
|
||||
mapstream::save_geometry(f);
|
||||
|
||||
if(yendor::on || tactic::on)
|
||||
|
@ -986,6 +989,102 @@ void save_mode_data(hstream& f) {
|
|||
f.write<char>(bow::weapon);
|
||||
f.write<char>(bow::style);
|
||||
}
|
||||
if(use_custom_land_list) {
|
||||
f.write<char>(3);
|
||||
f.write<int>(landtypes);
|
||||
for(int i=0; i<landtypes; i++) {
|
||||
f.write<char>(custom_land_list[i]);
|
||||
f.write<int>(custom_land_treasure[i]);
|
||||
f.write<int>(custom_land_difficulty[i]);
|
||||
f.write<int>(custom_land_wandering[i]);
|
||||
}
|
||||
}
|
||||
if(ls::horodisk_structure()) {
|
||||
f.write<char>(4);
|
||||
f.write<int>(horodisk_from);
|
||||
}
|
||||
if(land_structure == lsChaosRW) {
|
||||
f.write<char>(5);
|
||||
f.write<int>(randomwalk_size);
|
||||
}
|
||||
if(land_structure == lsLandscape) {
|
||||
f.write<char>(6);
|
||||
f.write<int>(landscape_div);
|
||||
}
|
||||
if(shmup::on && vid.creature_scale != 1) {
|
||||
f.write<char>(7);
|
||||
f.write<ld>(vid.creature_scale);
|
||||
}
|
||||
}
|
||||
|
||||
EX void load_mode_data_with_zero(hstream& f) {
|
||||
mapstream::load_geometry(f);
|
||||
|
||||
land_structure = (eLandStructure) f.get<char>();
|
||||
shmup::on = f.get<char>();
|
||||
inv::on = f.get<char>();
|
||||
#if CAP_TOUR
|
||||
tour::on = f.get<char>();
|
||||
#else
|
||||
f.get<char>();
|
||||
#endif
|
||||
peace::on = f.get<char>();
|
||||
peace::otherpuzzles = f.get<char>();
|
||||
peace::explore_other = f.get<char>();
|
||||
multi::players = f.get<char>();
|
||||
xcheat = f.get<char>();
|
||||
casual = false;
|
||||
bow::weapon = bow::wBlade;
|
||||
if(shmup::on) vid.creature_scale = 1;
|
||||
|
||||
while(true) {
|
||||
char option = f.get<char>();
|
||||
switch(option) {
|
||||
|
||||
case 0:
|
||||
return;
|
||||
|
||||
case 1:
|
||||
casual = true;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
bow::weapon = (bow::eWeapon) f.get<char>();
|
||||
bow::style = (bow::eCrossbowStyle) f.get<char>();
|
||||
break;
|
||||
|
||||
case 3: {
|
||||
use_custom_land_list = true;
|
||||
int lt = f.get<int>();
|
||||
if(lt > landtypes) throw hstream_exception("too many landtypes");
|
||||
for(int i=0; i<lt; i++) {
|
||||
custom_land_list[i] = f.get<char>();
|
||||
custom_land_treasure[i] = f.get<int>();
|
||||
custom_land_difficulty[i] = f.get<int>();
|
||||
custom_land_wandering[i] = f.get<int>();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 4:
|
||||
horodisk_from = f.get<int>();
|
||||
break;
|
||||
|
||||
case 5:
|
||||
randomwalk_size = f.get<int>();
|
||||
break;
|
||||
|
||||
case 6:
|
||||
landscape_div = f.get<int>();
|
||||
break;
|
||||
|
||||
case 7:
|
||||
vid.creature_scale = f.get<ld>();
|
||||
|
||||
default:
|
||||
throw hstream_exception("wrong option");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EX modecode_t modecode(int mode) {
|
||||
|
|
Loading…
Reference in New Issue