Angband Forums

Angband Forums (http://angband.oook.cz/forum/index.php)
-   ToME (http://angband.oook.cz/forum/forumdisplay.php?f=9)
-   -   ToME 2.4.0-ah released (http://angband.oook.cz/forum/showthread.php?t=8541)

AnonymousHero September 7, 2017 14:21

ToME 2.4.0-ah released
 
Hi all,

I've tagged and released ToME 2.4.0-ah. Source can be downloaded here: https://github.com/tome2/tome2/tree/v2.4.0-ah (Click "Clone or Download", Click "Download ZIP".)

This being a .0 version and given the extent of code changes, players should probably expect a few bugs. Please report any bugs you find here: https://github.com/tome2/tome2/issues

Changes:

Code:

Game:

- Removed traps and related skills. (Thanks to "miramor" for doing
  most of the actual work on this.)
- Removed Alchemist class from ToME module. They were horribly broken
  and encouraged only scummy play. They were also indirectly
  responsible for a lot of items that were junk to every other
  character class.
- Remove Runecrafer class.
- Increased size of the home drastically.
- Fix "far reaching attack" skill. (Thanks to "miramor".)
- Remove pointless player stats such as "gender", "age", "height",
  etc.
- Disallow casting for Posessors when they don't have enought SP.
  (aka "Remove system shock".)
- Magic Mapping now maps the whole level instead of only the display
  region.
- Summoned monsters appear around summoner instead of player.
- Remove various mostly inconsequential options.
- Use PCG random number generator instead of the old custom one.
- Grant player full monster knowledge.
- Theme: Fix final guardian artifact for Land of Mountains.
- Theme: Remove armor restriction for Eagle/Dragon races.

Build:

- Use C++14.
- Use (vendored) "cppformat" for string formatting.
- Use (vendored) "jsoncons" instead of "jansson".
- Produce individual executables for each of the supported platforms
  instead of a single executable.


Yottle September 7, 2017 15:20

Cool! It looks like you have dumped a lot of the dreck that never worked properly.

AnonymousHero September 7, 2017 16:14

Quote:

Originally Posted by Yottle (Post 123771)
Cool! It looks like you have dumped a lot of the dreck that never worked properly.

Yes, indeed.

Derakon September 7, 2017 17:22

These changes all look pretty solid. Glad to see this hoary old goat getting some attention. :)

Estie September 7, 2017 18:43

Aparently I am the only one who likes alchemists. I saw "removed" and stopped reading there :(

Derakon September 7, 2017 18:52

Quote:

Originally Posted by Estie (Post 123779)
Aparently I am the only one who likes alchemists. I saw "removed" and stopped reading there :(

I tried playing one once, but stopped when I realized that in order to make your own artifacts, you had to scum for a gigantic number of crafting ingredients.

It might be worth seeing if there's some way to retain the Alchemist's other abilities without having the scummy ultimate power and without polluting the dungeon with essences everywhere. The abilities to craft your own egos and to have a failure-free recharging method for high-level devices were both pretty neat. Maybe instead of having essences as separate items, you could use essences directly from items that "contain" them? So you could make a Freezing weapon using a stack of Potions of Resist Cold, because each potion contains a Cold essence. Or you could use wands/staves of the appropriate types as storage batteries.

Estie September 7, 2017 19:53

I have played many alchemists and never made more than 1 or 2 artifacts with each. The ability to blow up your toon out of proportion is there, but as you said, grindy and arguably boring. But 1. it is not the only way to get super toons, there are others in tome, 2. the interesting part about alchemists is actually the start - if you dont mind shopping for "properties", the things you get first make going to different dungeons viable; certainly thats a lot more interesting than the optimal melee start - orc cave to get the 3 guaranteed artifacts - and 3. there may be people who like that, grinding for ages to get 10k hp or such, whats wrong with it ?

As for essences, its a simple thing to automize them, naturally I do it with all non-alchemists from the start. The only changes I would like are weightless essences and indestructable quest essences (if they arent already, I havent tested that).

EpicMan September 7, 2017 20:05

Three cheers for your work on this, AnonymousHero. ToME is one of my favorite roguelikes.

Quote:

Originally Posted by Estie (Post 123784)
I have played many alchemists and never made more than 1 or 2 artifacts with each. The ability to blow up your toon out of proportion is there, but as you said, grindy and arguably boring. But 1. it is not the only way to get super toons, there are others in tome, 2. the interesting part about alchemists is actually the start - if you dont mind shopping for "properties", the things you get first make going to different dungeons viable; certainly thats a lot more interesting than the optimal melee start - orc cave to get the 3 guaranteed artifacts - and 3. there may be people who like that, grinding for ages to get 10k hp or such, whats wrong with it ?

Alchemist starts are fun because while your character starts out weak and unable to cast spells, but you start with (or able to immediately make) a potion of detonations, which can be thrown to kill a valuable target for multiple levels. It is a very different start than most other race/class combos.

They did add a lot of useless-for-everybody-else items to the game though. Maybe essences should be gained by destroying ego items/jewelry/etc, and make the player sacrifice an artifact to create a new one?

Derakon September 7, 2017 20:09

Quote:

Originally Posted by EpicMan (Post 123785)
Maybe essences should be gained by destroying ego items/jewelry/etc, and make the player sacrifice an artifact to create a new one?

Artifacts are in limitless supply, so you should really have to limit the power of the created artifact by the power of the destroyed artifact, or something similar. That sounds hard to balance, but could be pretty fun especially if it meant getting access to the artifact creation skill from the get-go (or at least comparatively early) rather than it not being available until after the player already has a surfeit of artifacts to play with.

Another possibility for essences is that they become some weightless, immaterial, non-inventory-item thing that is tracked separately. Like, when you drain an item, the essences go into an "essence pouch" which you can examine from ~, and essences never appear as items in the wild. Caves of Qud uses this approach for its crafting components.

wobbly September 7, 2017 20:24

Sangband has weightless essences likewise in a pouch. you used to find them near stuff of the same essence. Acid essenses near black dragon spawns. Death essenses near bad potions etc.

AnonymousHero September 7, 2017 20:55

I don't object to an Alchemist-like class on principle, but as it was it was just broken (IMO) and a significant contributor to the TMJ problem. Something like a device-master might be interesting, perhaps. (Yes, I'm also very aware that there are other classes where you can get crazy strong characters, but they usually have a limitations in other areas to sort-of-balance them. They can also be quite tricky and hard to pull off. An example would be a bare-hand possessor in a GWOP/Ancalagon's body which transitions to Anti-magic.)

Alchemy was also a ton (several thousand lines, IIRC) of really messy code. I'm trying to focus on improving the code quality gradually to (eventually) make it a lot easier to implement e.g. new classes (or whatever). A lot of the more niche classes/skills etc. stand in the way of that, so sometimes it's easier to just outright remove it. (I'm also considering removing MUSIC as a spell type since it's only usable by one very niche class, the Bard, and it adds a lot of code complexity.)

Yottle September 8, 2017 13:13

I enjoy playing alchemists occasionally, but for me the interesting part is the early going. Once I learn a few critical recipes like "elven" and "power" it is just a matter of grinding through. Usually I just dump the character and start over. Losing the class is a small price to pay for a more stable and easily maintained game, IMHO.
Personally, I think that Theme showed to best way to add variation to the game. There are many more types of characters, but they are differentiated through different starting attributes and/or gain of attributes at level gain. There are also many more interesting takes on dungeon construction, including some that are challenging even for maxed-out characters. That was all done without adding anything to the underlying code. She didn't use the alchemist class either.

Gwarl September 10, 2017 18:48

Compilation failed spectuacularly. Error log is far too long to post here.

Maybe we could get makefile.std back? Perhaps my gcc is outdated? what's going on?

HugoTheGreat2011 September 10, 2017 19:14

Quote:

Originally Posted by Gwarl (Post 123891)
Compilation failed spectuacularly. Error log is far too long to post here.

Maybe we could get makefile.std back? Perhaps my gcc is outdated? what's going on?

Gwarl, were you trying to compile 32-bit or 64-bit? Mac, Windows, or Linux version? AH will need this info to help out. :)

Gwarl September 10, 2017 20:42

64bit linux ubuntu

he's been doing ungodly things with c++ and filesystem libraries and who knows how all this works anymore?

AnonymousHero September 12, 2017 18:09

Quote:

Originally Posted by Gwarl (Post 123891)
Compilation failed spectuacularly. Error log is far too long to post here.

Maybe we could get makefile.std back? Perhaps my gcc is outdated? what's going on?

There's no makefile and there won't be one -- I switched over to CMake since it's much simpler to maintain and work with generally.

If you're getting lots of weird errors then feel free to post them here or on https://github.com/tome2/tome2/issues . It obviously should just work if you follow the instructions in the README. However, you do need a recent GCC/Clang. I think the requirement is something like GCC 6.1.0 or later -- it's bit hard to tell since C++14 has been quite spotty until recently, esp. regarding the 'relaxed constexpr'.. IIRC 'clang' was a bit better so might want to try with that. If you want to configure with clang, run

Code:

CC=/usr/bin/clang CXX=/usr/bin/clang++ cmake [...]
where the "[...]" bit is whatever else you want to configure with. (Again, see the README for specifics on that "..." bit.)

Gwarl September 12, 2017 18:28

The error log was vast, as if I were trying to compile a totally different language. I gave up after about five minutes of scrolling to see where the errors began.

Note: I changed the variable inside z-config.h from "./lib/" to the absoloute path of where I was going to put the lib files, and removed the lines marked as an option for using private_user_paths (I need to do this for every variant I run on the site).

I'll see about upgrading my GCC

Derakon September 12, 2017 18:30

Quote:

Originally Posted by Gwarl (Post 123949)
The error log was vast, as if I were trying to compile a totally different language. I gave up after about five minutes of scrolling to see where the errors began.

`problematic_command 2>&1 | less` is my go-to in that kind of situation.

AnonymousHero September 12, 2017 18:38

Quote:

Originally Posted by Gwarl (Post 123949)
The error log was vast, as if I were trying to compile a totally different language. I gave up after about five minutes of scrolling to see where the errors began.

Note: I changed the variable inside z-config.h from "./lib/" to the absoloute path of where I was going to put the lib files, and removed the lines marked as an option for using private_user_paths (I need to do this for every variant I run on the site).

I'll see about upgrading my GCC

Yeah, I'd try with a newer GCC first, at least if you have an older one :).

Usually only the first ~200 or so lines are needed -- I should be able to get an inkling of the problem from that.

You could also post the log in a GitHub gist or something. (Not sure if you have a GH account; there are also other free "paste-a-file" services like pastebin or whatever.).

EDIT: Derakon's advice is also good. You could also just clear the scrollback buffer in your terminal. (Terminals differ on how to do that, but I think almost all of them support clearing the buffer.)

Gwarl September 30, 2017 15:03

I upgrade my gcc. This happened:

Quote:

[ 21%] Building CXX object src/CMakeFiles/game.dir/files.cc.o
/home/angbandlive/src/tome2/src/files.cc:1977:121: error: ‘{anonymous}::detail::object_flag_cell_empty’ is not a valid template argument for type ‘const {anonymous}::object_flag_cell&’ because object ‘{anonymous}::detail::object_flag_cell_empty’ has not external linkage
using object_flag_cell_monoid = monoid<object_flag_cell, detail::object_flag_cell_append, detail::object_flag_cell_empty>;
^
/home/angbandlive/src/tome2/src/files.cc: In function ‘void {anonymous}::display_flag_row(int, int, const std::vector<std::tuple<char, int, flag_set<6ul> > >&, const std::vector<const object_flag_meta*>&)’:
/home/angbandlive/src/tome2/src/files.cc:2049:13: error: ‘object_flag_cell_monoid’ has not been declared
auto acc = object_flag_cell_monoid::empty;
^
/home/angbandlive/src/tome2/src/files.cc:2054:31: error: ‘object_flag_cell_monoid’ has not been declared
object_flag_cell combined = object_flag_cell_monoid::empty;
^
/home/angbandlive/src/tome2/src/files.cc:2066:17: error: ‘object_flag_cell_monoid’ has not been declared
combined = object_flag_cell_monoid::append(
^
/home/angbandlive/src/tome2/src/files.cc:2074:9: error: ‘object_flag_cell_monoid’ has not been declared
acc = object_flag_cell_monoid::append(acc, combined);
^
src/CMakeFiles/game.dir/build.make:398: recipe for target 'src/CMakeFiles/game.dir/files.cc.o' failed
make[3]: *** [src/CMakeFiles/game.dir/files.cc.o] Error 1
CMakeFiles/Makefile2:251: recipe for target 'src/CMakeFiles/game.dir/all' failed
make[2]: *** [src/CMakeFiles/game.dir/all] Error 2
CMakeFiles/Makefile2:226: recipe for target 'src/CMakeFiles/tome-gcu.dir/rule' failed
make[1]: *** [src/CMakeFiles/tome-gcu.dir/rule] Error 2
Makefile:201: recipe for target 'tome-gcu' failed
make: *** [tome-gcu] Error 2
Please advise?

AnonymousHero October 2, 2017 16:48

Your gcc is still to old. Which version are you using, i.e. what is the output of

Code:

gcc --version
?

Also note that if you have multiple versions installed, you might want to re-run the "cmake" command and make sure that it's spitting out the right version at the top of the output. It should look something like this:

Code:

-- The C compiler identification is GNU 7.2.0
-- The CXX compiler identification is GNU 7.2.0

(obviously version numbers might differ, this is just to make absolutely sure it's picking up the right version.)

Gwarl October 7, 2017 15:06

Code:

angbandlive@gwarl:~/src/unfixed/tome2$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/5/lto-wrapper
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 5.4.0-6ubuntu1~16.04.4' --with-bugurl=file:///usr/share/doc/gcc-5/README.Bugs --enable-languages=c,ada,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-5 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-libmpx --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-5-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-5-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-5-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.4)

Code:

angbandlive@gwarl:~/src/unfixed/tome2$ gcc-6 -v
Using built-in specs.
COLLECT_GCC=gcc-6
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/6/lto-wrapper
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu/Linaro 6.3.0-18ubuntu2~16.04' --with-bugurl=file:///usr/share/doc/gcc-6/README.Bugs --enable-languages=c,ada,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-6 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-libmpx --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-6-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-6-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-6-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --with-target-system-zlib --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 6.3.0 20170519 (Ubuntu/Linaro 6.3.0-18ubuntu2~16.04)
angbandlive@gwarl:~/src/unfixed/tome2$

How do I tell cmake to use gcc-6 instead of gcc? (in a makefile I could just edit the line specifying the compiler)

AnonymousHero October 7, 2017 19:11

Aha, it is as I suspected! :) I think doing

Code:

CC=gcc-6 CXX=g++-6 cmake
(and adding whatever else you need at the end) should do it!

Gwarl October 8, 2017 17:17

Code:

[ 29%] Building CXX object src/CMakeFiles/game.dir/init2.cc.o
/home/angbandlive/src/unfixed/tome2/src/init2.cc: In function ‘void init_file_paths(char*)’:
/home/angbandlive/src/unfixed/tome2/src/init2.cc:216:31: error: ‘PRIVATE_USER_PATH’ was not declared in this scope
  path_parse(user_path, 1024, PRIVATE_USER_PATH);
                              ^~~~~~~~~~~~~~~~~
src/CMakeFiles/game.dir/build.make:638: recipe for target 'src/CMakeFiles/game.dir/init2.cc.o' failed
make[3]: *** [src/CMakeFiles/game.dir/init2.cc.o] Error 1
CMakeFiles/Makefile2:97: recipe for target 'src/CMakeFiles/game.dir/all' failed
make[2]: *** [src/CMakeFiles/game.dir/all] Error 2
CMakeFiles/Makefile2:148: recipe for target 'src/CMakeFiles/tome-gcu.dir/rule' failed
make[1]: *** [src/CMakeFiles/tome-gcu.dir/rule] Error 2
Makefile:175: recipe for target 'tome-gcu' failed
make: *** [tome-gcu] Error 2

This makes it so goddamn hard to hack. I don't want to use private user paths, so I remove the thing marked in config.h as /*OPTION: private user paths*/ in order to configure the executable not to do so, right?

No.

I'll have another go at this later.

HugoTheGreat2011 October 8, 2017 17:53

Looking at your recent issue with TOME 2.4.0...were you compiling this within the angband.live webserver directory?

Gwarl October 9, 2017 13:13

Okay after all my complaining it's finally up!

here's the altered main-gcu.c


Code:

/* File: main-gcu.c */

/*
 * Copyright (c) 1997 Ben Harrison, and others
 *
 * This software may be copied and distributed for educational, research,
 * and not for profit purposes provided that this copyright and statement
 * are included in all such copies.
 */


/*
 * This file helps Angband run on Unix/Curses machines.
 *
 *
 * To use this file, you must define "USE_GCU" in the Makefile.
 *
 *
 * Note that this file is not "intended" to support non-Unix machines,
 * nor is it intended to support VMS or other bizarre setups.
 *
 * Also, this package assumes that the underlying "curses" handles both
 * the "nonl()" and "cbreak()" commands correctly, see the "OPTION" below.
 *
 * This code should work with most versions of "curses" or "ncurses",
 * and the "main-ncu.c" file (and USE_NCU define) are no longer used.
 *
 * This file provides up to 4 term windows.
 *
 * This file will attempt to redefine the screen colors to conform to
 * standard Angband colors.  It will only do so if the terminal type
 * indicates that it can do so.  See the page:
 *
 *    http://www.umr.edu/~keldon/ang-patch/ncurses_color.html
 *
 * for information on this.
 *
 * Consider the use of "savetty()" and "resetty()".  XXX XXX XXX
 */

#include "main.h"
#include "util.h"
#include "variable.h"


#include <limits.h>

/*
 * Hack -- play games with "bool" and "term"
 */
#undef bool

/* Avoid 'struct term' name conflict with <curses.h> (via <term.h>) on AIX */
#define term System_term

/*
 * Include the proper "header" file
 */
#ifdef USE_NCURSES
# include <ncurses.h>
#else
# include <curses.h>
#endif

#undef term

/*
 * Try redefining the colors at startup.
 */
#define REDEFINE_COLORS


/*
 * Hack -- try to guess which systems use what commands
 * Hack -- allow one of the "USE_Txxxxx" flags to be pre-set.
 * Mega-Hack -- try to guess when "POSIX" is available.
 * If the user defines two of these, we will probably crash.
 */
#if !defined(USE_TPOSIX)
# if !defined(USE_TERMIO) && !defined(USE_TCHARS)
# if defined(_POSIX_VERSION)
# define USE_TPOSIX
# else
# if defined(linux)
# define USE_TERMIO
# else
# define USE_TCHARS
# endif
# endif
# endif
#endif

/*
 * POSIX stuff
 */
#ifdef USE_TPOSIX
# include <sys/ioctl.h>
# include <termios.h>
#endif

/*
 * One version needs these files
 */
#ifdef USE_TERMIO
# include <sys/ioctl.h>
# include <termio.h>
#endif

/*
 * The other needs these files
 */
#ifdef USE_TCHARS
# include <sys/ioctl.h>
# include <sys/resource.h>
# include <sys/param.h>
# include <sys/file.h>
#endif

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>



/*
 * XXX XXX Hack -- POSIX uses "O_NONBLOCK" instead of "O_NDELAY"
 *
 * They should both work due to the "(i != 1)" test below.
 */
#ifndef O_NDELAY
# define O_NDELAY O_NONBLOCK
#endif


/*
 * OPTION: some machines lack "cbreak()"
 * On these machines, we use an older definition
 */
/* #define cbreak() crmode() */


/*
 * OPTION: some machines cannot handle "nonl()" and "nl()"
 * On these machines, we can simply ignore those commands.
 */
/* #define nonl() */
/* #define nl() */


/*
 * Save the "normal" and "angband" terminal settings
 */

#ifdef USE_TPOSIX

static struct termios norm_termios;

static struct termios game_termios;

#endif

#ifdef USE_TERMIO

static struct termio norm_termio;

static struct termio game_termio;

#endif

#ifdef USE_TCHARS

static struct ltchars norm_special_chars;
static struct sgttyb norm_ttyb;
static struct tchars norm_tchars;
static int norm_local_chars;

static struct ltchars game_special_chars;
static struct sgttyb game_ttyb;
static struct tchars game_tchars;
static int game_local_chars;

#endif

/*
 * Information about a term
 */
typedef struct term_data term_data;

struct term_data
{
        term t;                  /* All term info */

        WINDOW *win;            /* Pointer to the curses window */
};

/* Max number of windows on screen */
#define MAX_TERM_DATA 4

/* Information about our windows */
static term_data data[MAX_TERM_DATA];


/*
 * Hack -- Number of initialized "term" structures
 */
static int active = 0;


#ifdef A_COLOR

/*
 * Hack -- define "A_BRIGHT" to be "A_BOLD", because on many
 * machines, "A_BRIGHT" produces ugly "inverse" video.
 */
#ifndef A_BRIGHT
# define A_BRIGHT A_BOLD
#endif

/*
 * Software flag -- we are allowed to use color
 */
static int can_use_color = FALSE;

/*
 * Software flag -- we are allowed to change the colors
 */
static int can_fix_color = FALSE;

/*
 * Simple Angband to Curses color conversion table
 */
static int colortable[16];

/**
 * Background color we should draw with; either BLACK or DEFAULT
 */
static int bg_color = COLOR_BLACK;

#endif



/*
 * Place the "keymap" into its "normal" state
 */
static void keymap_norm(void)
{

#ifdef USE_TPOSIX

        /* restore the saved values of the special chars */
        (void)tcsetattr(0, TCSAFLUSH, &norm_termios);

#endif

#ifdef USE_TERMIO

        /* restore the saved values of the special chars */
        (void)ioctl(0, TCSETA, (char *)&norm_termio);

#endif

#ifdef USE_TCHARS

        /* restore the saved values of the special chars */
        (void)ioctl(0, TIOCSLTC, (char *)&norm_special_chars);
        (void)ioctl(0, TIOCSETP, (char *)&norm_ttyb);
        (void)ioctl(0, TIOCSETC, (char *)&norm_tchars);
        (void)ioctl(0, TIOCLSET, (char *)&norm_local_chars);

#endif

}


/*
 * Place the "keymap" into the "game" state
 */
static void keymap_game(void)
{

#ifdef USE_TPOSIX

        /* restore the saved values of the special chars */
        (void)tcsetattr(0, TCSAFLUSH, &game_termios);

#endif

#ifdef USE_TERMIO

        /* restore the saved values of the special chars */
        (void)ioctl(0, TCSETA, (char *)&game_termio);

#endif

#ifdef USE_TCHARS

        /* restore the saved values of the special chars */
        (void)ioctl(0, TIOCSLTC, (char *)&game_special_chars);
        (void)ioctl(0, TIOCSETP, (char *)&game_ttyb);
        (void)ioctl(0, TIOCSETC, (char *)&game_tchars);
        (void)ioctl(0, TIOCLSET, (char *)&game_local_chars);

#endif

}


/*
 * Save the normal keymap
 */
static void keymap_norm_prepare(void)
{

#ifdef USE_TPOSIX

        /* Get the normal keymap */
        tcgetattr(0, &norm_termios);

#endif

#ifdef USE_TERMIO

        /* Get the normal keymap */
        (void)ioctl(0, TCGETA, (char *)&norm_termio);

#endif

#ifdef USE_TCHARS

        /* Get the normal keymap */
        (void)ioctl(0, TIOCGETP, (char *)&norm_ttyb);
        (void)ioctl(0, TIOCGLTC, (char *)&norm_special_chars);
        (void)ioctl(0, TIOCGETC, (char *)&norm_tchars);
        (void)ioctl(0, TIOCLGET, (char *)&norm_local_chars);

#endif

}


/*
 * Save the keymaps (normal and game)
 */
static void keymap_game_prepare(void)
{

#ifdef USE_TPOSIX

        /* Acquire the current mapping */
        tcgetattr(0, &game_termios);

        /* Force "Ctrl-C" to interupt */
        game_termios.c_cc[VINTR] = (char)3;

        /* Force "Ctrl-Z" to suspend */
        game_termios.c_cc[VSUSP] = (char)26;

        /* Hack -- Leave "VSTART/VSTOP" alone */

        /* Disable the standard control characters */
        game_termios.c_cc[VQUIT] = (char) - 1;
        game_termios.c_cc[VERASE] = (char) - 1;
        game_termios.c_cc[VKILL] = (char) - 1;
        game_termios.c_cc[VEOF] = (char) - 1;
        game_termios.c_cc[VEOL] = (char) - 1;

        /* Normally, block until a character is read */
        game_termios.c_cc[VMIN] = 1;
        game_termios.c_cc[VTIME] = 0;

#endif

#ifdef USE_TERMIO

        /* Acquire the current mapping */
        (void)ioctl(0, TCGETA, (char *)&game_termio);

        /* Force "Ctrl-C" to interupt */
        game_termio.c_cc[VINTR] = (char)3;

        /* Force "Ctrl-Z" to suspend */
        game_termio.c_cc[VSUSP] = (char)26;

        /* Hack -- Leave "VSTART/VSTOP" alone */

        /* Disable the standard control characters */
        game_termio.c_cc[VQUIT] = (char) - 1;
        game_termio.c_cc[VERASE] = (char) - 1;
        game_termio.c_cc[VKILL] = (char) - 1;
        game_termio.c_cc[VEOF] = (char) - 1;
        game_termio.c_cc[VEOL] = (char) - 1;

        /* Normally, block until a character is read */
        game_termio.c_cc[VMIN] = 1;
        game_termio.c_cc[VTIME] = 0;

#endif

#ifdef USE_TCHARS

        /* Get the default game characters */
        (void)ioctl(0, TIOCGETP, (char *)&game_ttyb);
        (void)ioctl(0, TIOCGLTC, (char *)&game_special_chars);
        (void)ioctl(0, TIOCGETC, (char *)&game_tchars);
        (void)ioctl(0, TIOCLGET, (char *)&game_local_chars);

        /* Force suspend (^Z) */
        game_special_chars.t_suspc = (char)26;

        /* Cancel some things */
        game_special_chars.t_dsuspc = (char) - 1;
        game_special_chars.t_rprntc = (char) - 1;
        game_special_chars.t_flushc = (char) - 1;
        game_special_chars.t_werasc = (char) - 1;
        game_special_chars.t_lnextc = (char) - 1;

        /* Force interupt (^C) */
        game_tchars.t_intrc = (char)3;

        /* Force start/stop (^Q, ^S) */
        game_tchars.t_startc = (char)17;
        game_tchars.t_stopc = (char)19;

        /* Cancel some things */
        game_tchars.t_quitc = (char) - 1;
        game_tchars.t_eofc = (char) - 1;
        game_tchars.t_brkc = (char) - 1;

#endif

}




/*
 * Suspend/Resume
 */
static errr Term_xtra_gcu_alive(int v)
{
        int x, y;


        /* Suspend */
        if (!v)
        {
                /* Go to normal keymap mode */
                keymap_norm();

                /* Restore modes */
                noraw();
                echo();
                nl();

                /* Hack -- make sure the cursor is visible */
                Term_xtra(TERM_XTRA_SHAPE, 1);

                /* Flush the curses buffer */
                (void)refresh();

                /* Get current cursor position */
                getyx(curscr, y, x);

                /* Move the cursor to bottom right corner */
                mvcur(y, x, LINES - 1, 0);

                /* Exit curses */
                endwin();

                /* Flush the output */
                (void)fflush(stdout);
        }

        /* Resume */
        else
        {
                /* Refresh */
                /* (void)touchwin(curscr); */
                /* (void)wrefresh(curscr); */

                /* Restore the settings */
                raw();
                noecho();
                nonl();

                /* Go to angband keymap mode */
                keymap_game();
        }

        /* Success */
        return (0);
}


/*
 * Init the "curses" system
 */
static void Term_init_gcu(term *t)
{
        term_data *td = (term_data *)(t->data);

        /* Count init's, handle first */
        if (active++ != 0) return;

        /* Erase the window */
        (void)wclear(td->win);

        /* Reset the cursor */
        (void)wmove(td->win, 0, 0);

        /* Flush changes */
        (void)wrefresh(td->win);

        /* Game keymap */
        keymap_game();
}


/*
 * Nuke the "curses" system
 */
static void Term_nuke_gcu(term *t)
{
        int x, y;
        term_data *td = (term_data *)(t->data);

        /* Delete this window */
        delwin(td->win);

        /* Count nuke's, handle last */
        if (--active != 0) return;

        /* Hack -- make sure the cursor is visible */
        Term_xtra(TERM_XTRA_SHAPE, 1);

#ifdef A_COLOR
        /* Reset colors to defaults */
        start_color();
#endif

        /* Get current cursor position */
        getyx(curscr, y, x);

        /* Move the cursor to bottom right corner */
        mvcur(y, x, LINES - 1, 0);

        /* Flush the curses buffer */
        (void)refresh();

        /* Exit curses */
        endwin();

        /* Flush the output */
        (void)fflush(stdout);

        /* Normal keymap */
        keymap_norm();
}


/*
* Process events (with optional wait)
*/
static errr Term_xtra_gcu_event(int v)
{
        int i, k;

        char buf[2];

        /* Wait */
        if (v)
        {
                /* Wait for one byte */
                i = read(0, buf, 1);

                /* Hack -- Handle bizarre "errors" */
                if ((i <= 0) && (errno != EINTR)) abort();
        }

        /* Do not wait */
        else
        {
                /* Get the current flags for stdin */
                k = fcntl(0, F_GETFL, 0);

                /* Oops */
                if (k < 0) return (1);

                /* Tell stdin not to block */
                if (fcntl(0, F_SETFL, k | O_NDELAY) < 0) return (1);

                /* Read one byte, if possible */
                i = read(0, buf, 1);

                /* Replace the flags for stdin */
                if (fcntl(0, F_SETFL, k)) return (1);
        }

        /* Ignore "invalid" keys */
        if ((i != 1) || (!buf[0])) return (1);

        /* Enqueue the keypress */
        Term_keypress(buf[0]);

        /* Success */
        return (0);
}

static int scale_color(int i, int j, int scale)
{
    return (angband_color_table[i][j] * (scale - 1) + 127) / 255;
}

static int create_color(int i, int scale)
{
    int r = scale_color(i, 1, scale);
    int g = scale_color(i, 2, scale);
    int b = scale_color(i, 3, scale);
    int rgb = 16 + scale * scale * r + scale * g + b;
    /* In the case of white and black we need to use the ANSI colors */
    if (r == g && g == b)
    {
        if (b == 0) rgb = 0;
        if (b == scale) rgb = 15;
    }
    return rgb;
}

/*
 * React to changes
 */
static errr Term_xtra_gcu_react(void)
{

#ifdef A_COLOR
    if (COLORS == 256 || COLORS == 88)
    {
        /* CTK: I snagged this color handling from current Vanilla */
        /* If we have more than 16 colors, find the best matches. These numbers
        * correspond to xterm/rxvt's builtin color numbers--they do not
        * correspond to curses' constants OR with curses' color pairs.
        *
        * XTerm has 216 (6*6*6) RGB colors, with each RGB setting 0-5.
        * RXVT has 64 (4*4*4) RGB colors, with each RGB setting 0-3.
        *
        * Both also have the basic 16 ANSI colors, plus some extra grayscale
        * colors which we do not use.
        */
        int i;
        int scale = COLORS == 256 ? 6 : 4;
        for (i = 0; i < 16; i++)
        {
            int fg = create_color(i, scale);
            init_pair(i + 1, fg, bg_color);
            colortable[i] = COLOR_PAIR(i + 1) | A_NORMAL;
        }
    }

#endif

        /* Success */
        return (0);
}


/*
 * Handle a "special request"
 */
static errr Term_xtra_gcu(int n, int v)
{
        term_data *td = (term_data *)(Term->data);

        /* Analyze the request */
        switch (n)
        {
                /* Clear screen */
        case TERM_XTRA_CLEAR:
                touchwin(td->win);
                (void)wclear(td->win);
                return (0);

                /* Make a noise */
        case TERM_XTRA_NOISE:
                (void)write(1, "\007", 1);
                return (0);

                /* Flush the Curses buffer */
        case TERM_XTRA_FRESH:
                (void)wrefresh(td->win);
                return (0);


                /* Suspend/Resume curses */
        case TERM_XTRA_ALIVE:
                return (Term_xtra_gcu_alive(v));

                /* Process events */
        case TERM_XTRA_EVENT:
                return (Term_xtra_gcu_event(v));

                /* Flush events */
        case TERM_XTRA_FLUSH:
                while (!Term_xtra_gcu_event(FALSE));
                return (0);

                /* React to events */
        case TERM_XTRA_REACT:
                Term_xtra_gcu_react();
                return (0);
        }

        /* Unknown */
        return (1);
}


/*
 * Actually MOVE the hardware cursor
 */
static errr Term_curs_gcu(int x, int y)
{
        term_data *td = (term_data *)(Term->data);

        /* Literally move the cursor */
        wmove(td->win, y, x);

        /* Success */
        return (0);
}


/*
 * Place some text on the screen using an attribute
 */
static errr Term_text_gcu(int x, int y, int n, byte a, cptr s)
{
        term_data *td = (term_data *)(Term->data);

        int i;

#ifdef A_COLOR
        /* Set the color */
        if (can_use_color) wattrset(td->win, colortable[a & 0x0F]);
#endif

        /* Move the cursor */
        wmove(td->win, y, x);

        /* Draw each character */
        for (i = 0; i < n; i++)
        {

                /* Draw a normal character */
                waddch(td->win, (byte)s[i]);
        }

        /* Success */
        return (0);
}


/*
 * Create a window for the given "term_data" argument.
 *
 * Assumes legal arguments.
 */
static errr term_data_init_gcu(term_data *td, int rows, int cols, int y, int x)
{
        term *t = &td->t;

        /* Create new window */
        td->win = newwin(rows, cols, y, x);

        /* Check for failure */
        if (!td->win)
        {
                /* Error */
                quit("Failed to setup curses window.");
        }

        /* Initialize the term */
        term_init(t, cols, rows, 256);

        /* Avoid bottom right corner */
        t->icky_corner = TRUE;

        /* Set some hooks */
        t->init_hook = Term_init_gcu;
        t->nuke_hook = Term_nuke_gcu;

        /* Set some more hooks */
        t->text_hook = Term_text_gcu;
        t->curs_hook = Term_curs_gcu;
        t->xtra_hook = Term_xtra_gcu;

        /* Save the data */
        t->data = td;

        /* Activate it */
        Term_activate(t);

        /* Success */
        return (0);
}


static void hook_quit(cptr str)
{
        /* Unused */
        (void)str;

        /* Exit curses */
        endwin();
}


/*
 * Prepare "curses" for use by the file "z-term.c"
 *
 * Installs the "hook" functions defined above, and then activates
 * the main screen "term", which clears the screen and such things.
 *
 * Someone should really check the semantics of "initscr()"
 */
int init_gcu(int argc, char **argv)
{
        int i;

        int num_term = MAX_TERM_DATA, next_win = 0;

        bool_ use_big_screen = FALSE;


        /* Parse args */
        for (i = 1; i < argc; i++)
        {
                if (prefix(argv[i], "-b"))
                {
                        use_big_screen = TRUE;
                        continue;
                }

                fprintf(stderr, "Ignoring option: %s", argv[i]);
        }


        /* Extract the normal keymap */
        keymap_norm_prepare();


/* Initialize for other systems */
        if (initscr() == (WINDOW*)ERR) return ( -1);

        /* Activate hooks */
        quit_aux = hook_quit;

        /* Require standard size screen */
        if ((LINES < 24) || (COLS < 80))
        {
                quit("Angband needs at least an 80x24 'curses' screen");
        }



#ifdef A_COLOR

        /*** Init the Color-pairs and set up a translation table ***/

        /* Do we have color, and enough color, available? */
        can_use_color = ((start_color() != ERR) && has_colors() &&
                        (COLORS >= 8) && (COLOR_PAIRS >= 8));

#ifdef REDEFINE_COLORS

        /* Can we change colors? */
        can_fix_color = (can_use_color && can_change_color() &&
                        (COLORS >= 16) && (COLOR_PAIRS > 8));

#endif

        /* Attempt to use customized colors */
        if (can_fix_color)
        {
                /* Prepare the color pairs */
                for (i = 1; i <= 8; i++)
                {
                        /* Reset the color */
                        if (init_pair(i, i - 1, 0) == ERR)
                        {
                                quit("Color pair init failed");
                        }

                        /* Set up the colormap */
                        colortable[i - 1] = (COLOR_PAIR(i) | A_NORMAL);
                        colortable[i + 7] = (COLOR_PAIR(i) | A_BRIGHT);
                }

                /* Take account of "gamma correction" XXX XXX XXX */

                /* Prepare the "Angband Colors" */
                Term_xtra_gcu_react();
        }

        /* Attempt to use colors */
        else if (can_use_color)
        {
                /* Color-pair 0 is *always* WHITE on BLACK */

                /* Prepare the color pairs */
                init_pair(1, COLOR_RED, COLOR_BLACK);
                init_pair(2, COLOR_GREEN, COLOR_BLACK);
                init_pair(3, COLOR_YELLOW, COLOR_BLACK);
                init_pair(4, COLOR_BLUE, COLOR_BLACK);
                init_pair(5, COLOR_MAGENTA, COLOR_BLACK);
                init_pair(6, COLOR_CYAN, COLOR_BLACK);
                init_pair(7, COLOR_BLACK, COLOR_BLACK);

                /* Prepare the "Angband Colors" -- Bright white is too bright */
                colortable[0] = (COLOR_PAIR(7) | A_NORMAL);        /* Black */
                colortable[1] = (COLOR_PAIR(0) | A_NORMAL);        /* White */
                colortable[2] = (COLOR_PAIR(6) | A_NORMAL);        /* Grey XXX */
                colortable[3] = (COLOR_PAIR(1) | A_BRIGHT);        /* Orange XXX */
                colortable[4] = (COLOR_PAIR(1) | A_NORMAL);        /* Red */
                colortable[5] = (COLOR_PAIR(2) | A_NORMAL);        /* Green */
                colortable[6] = (COLOR_PAIR(4) | A_NORMAL);        /* Blue */
                colortable[7] = (COLOR_PAIR(3) | A_NORMAL);        /* Umber */
                colortable[8] = (COLOR_PAIR(7) | A_BRIGHT);        /* Dark-grey XXX */
                colortable[9] = (COLOR_PAIR(6) | A_BRIGHT);        /* Light-grey XXX */
                colortable[10] = (COLOR_PAIR(5) | A_NORMAL);        /* Purple */
                colortable[11] = (COLOR_PAIR(3) | A_BRIGHT);        /* Yellow */
                colortable[12] = (COLOR_PAIR(5) | A_BRIGHT);        /* Light Red XXX */
                colortable[13] = (COLOR_PAIR(2) | A_BRIGHT);        /* Light Green */
                colortable[14] = (COLOR_PAIR(4) | A_BRIGHT);        /* Light Blue */
                colortable[15] = (COLOR_PAIR(3) | A_NORMAL);        /* Light Umber XXX */
        }

#endif


        /*** Low level preparation ***/


        /* Prepare */
        raw();
        noecho();
        nonl();

        /* Extract the game keymap */
        keymap_game_prepare();


        /*** Now prepare the term(s) ***/

        /* Big screen -- one big term */
        if (use_big_screen)
        {
                /* Create a term */
                term_data_init_gcu(&data[0], LINES, COLS, 0, 0);

                /* Remember the term */
                angband_term[0] = &data[0].t;
        }

        /* No big screen -- create as many term windows as possible */
        else
        {
                /* Create several terms */
                for (i = 0; i < num_term; i++)
                {
                        int rows, cols, y, x;

                        /* Decide on size and position */
                        switch (i)
                        {
                                /* Upper left */
                        case 0:
                                {
                                        rows = 24;
                                        cols = 80;
                                        y = x = 0;
                                        break;
                                }

                                /* Lower left */
                        case 1:
                                {
                                        rows = LINES - 25;
                                        cols = 80;
                                        y = 25;
                                        x = 0;
                                        break;
                                }

                                /* Upper right */
                        case 2:
                                {
                                        rows = 24;
                                        cols = COLS - 81;
                                        y = 0;
                                        x = 81;
                                        break;
                                }

                                /* Lower right */
                        case 3:
                                {
                                        rows = LINES - 25;
                                        cols = COLS - 81;
                                        y = 25;
                                        x = 81;
                                        break;
                                }

                                /* XXX */
                        default:
                                {
                                        rows = cols = y = x = 0;
                                        break;
                                }
                        }

                        /* Skip non-existant windows */
                        if (rows <= 0 || cols <= 0) continue;

                        /* Create a term */
                        term_data_init_gcu(&data[next_win], rows, cols, y, x);

                        /* Remember the term */
                        angband_term[next_win] = &data[next_win].t;

                        /* One more window */
                        next_win++;
                }
        }

        /* Activate the "Angband" window screen */
        Term_activate(&data[0].t);

        /* Remember the active screen */
        term_screen = &data[0].t;

        /* Success */
        return (0);
}

int main(int argc, char *argv[])
{
        return main_real(
                argc,
                argv,
                "gcu",
                init_gcu,
                "  -- -b              Requests big screen\n");
}


AnonymousHero October 10, 2017 08:41

Fantastic that you got it working!

As you've probably discovered the idea with PRIVATE_USER_PATH would be to define it to something else (not containing "~", that's the bit that signifies the user's home directory), not to remove the definition.

(Apologies for the response lag, I'm sick with the flu at the moment.)

EDIT: Any chance you could make a GitHub gist with that file? I'd like to compare it to the current one to see if it's reasonable to just include directly in the repository.

Gwarl October 11, 2017 11:49

https://gist.github.com/OwenGHB/036c...53395d0027200d

Dudemanbroski December 11, 2017 00:36

Hey!
Could someone either offer me pre-compiled Windows binaries for this or alternatively step-by-step instructions for compiling this myself. Compiling under Windows is something I've never really learned to do.

Gwarl July 19, 2018 15:42

bump because I went and compiled this again on ubuntu (without fancy installaton options this time) and found my own posts here when googling resultant errors.

If you are compiling on Ubuntu, besides what the readme tells you, you'll need gcc-7 (or 6) which isn't available on the Ubuntu xenial repos. To get it:

Quote:

sudo add-apt-repository ppa:ubuntu-toolchain-r/test
sudo apt-get update
sudo apt-get install gcc-7 g++-7
then use
Quote:

CC=gcc-7 CXX=g++-7 make
The ubuntu section of the Readme.md could maybe use this info.

(note I haven't successfully compiled it yet, will edit when I figure out what else is wrong)

I've tried with 6 and 7 now and double checked I have all the releveant libraries installed and I'm still getting the error I posted before being told my compiler was still too old, argh, can't remember what I did to have this work before

AnonymousHero July 19, 2018 19:38

I'm starting to wonder if I shouldn't just provide a Docker container which the correct toolchain pre-setup just for compiling...

Sky July 20, 2018 09:46

Broadly speaking ... what are the differences between TOME 1, 2, 3 and 4?

I played tome 1 and iirc it was similar to angband in style - although it had wilderness, colors, quests - many of the stats, commands, gameplay were similar.

But then i played tome 4 - Tales Of Copyright Infringment - that did away with the tolkien setting and changed pretty much everything.

When did the big change happen? What is the last angband-esque build?? (And where can i find it?)

wobbly July 20, 2018 09:53

Tome 3 doesn't exist. It was Darkgod's 1st attempt at the new engine. He ended up abandoning it and writing T4. The 1st versions of T4 are still middle earth, though that's stretching it. The last version based on angband, you're probably in the thread for it? Not really an expert on Tome.

Derakon July 20, 2018 16:19

ToME 2 is the last Angband-like ToME. This is the thread for the most recent release of that line.

ToME 1 was called PernAngband and got hit by a C&D from Anne McCaffrey's lawyers, so 2 stripped out the Pern references at the same time that it bumped the version number.

Gwarl August 7, 2018 18:42

For apparently no reason at all I managed to build it this time, having done exactly the same thing I did last time.

However, I don't seem to be able to specify the user directory from the command line? I don't remember having this problem before.

Gwarl August 7, 2018 19:26

grabbed the 2.4.0 release and I have the same problem.

looking at main.c I don't see anywhere that the user directory is parsed.

this makes no sense because I swear this worked before.

AnonymousHero August 8, 2018 21:16

Quote:

Originally Posted by Gwarl (Post 132558)
grabbed the 2.4.0 release and I have the same problem.

looking at main.c I don't see anywhere that the user directory is parsed.

this makes no sense because I swear this worked before.

Are/were you using the TOME_PATH environment variable, or...?

AFAIR it should still work -- I certainly haven't done anything to remove it or anything like that.

Gwarl August 9, 2018 11:50

In my archive of the old site, in the source folder I have, within a folder labelled tome2-2.3.6-ah a main.c file with the following function:

Quote:

/*
* Handle a "-d<what>=<path>" option
*
* The "<what>" can be any string starting with the same letter as the
* name of a subdirectory of the "lib" folder (i.e. "i" or "info").
*
* The "<path>" can be any legal path for the given system, and should
* not end in any special path separator (i.e. "/tmp" or "~/.ang-info").
*/
static void change_path(cptr info)
{
cptr s;

/* Find equal sign */
s = strchr(info, '=');

/* Verify equal sign */
if (!s) quit_fmt("Try '-d<what>=<path>' not '-d%s'", info);

/* Analyze */
switch (tolower(info[0]))
{
case 'a':
{
string_free(ANGBAND_DIR_APEX);
ANGBAND_DIR_APEX = string_make(s + 1);
break;
}

case 'f':
{
string_free(ANGBAND_DIR_FILE);
ANGBAND_DIR_FILE = string_make(s + 1);
break;
}

case 'h':
{
string_free(ANGBAND_DIR_HELP);
ANGBAND_DIR_HELP = string_make(s + 1);
break;
}

case 'i':
{
string_free(ANGBAND_DIR_INFO);
ANGBAND_DIR_INFO = string_make(s + 1);
break;
}

case 'u':
{
string_free(ANGBAND_DIR_USER);
ANGBAND_DIR_USER = string_make(s + 1);
break;
}

case 'x':
{
string_free(ANGBAND_DIR_XTRA);
ANGBAND_DIR_XTRA = string_make(s + 1);
break;
}

#ifdef VERIFY_SAVEFILE

case 'b':
case 'd':
case 'e':
case 's':
{
quit_fmt("Restricted option '-d%s'", info);
}

#else /* VERIFY_SAVEFILE */

case 'b':
{
string_free(ANGBAND_DIR_BONE);
ANGBAND_DIR_BONE = string_make(s + 1);
break;
}

case 'd':
{
string_free(ANGBAND_DIR_DATA);
ANGBAND_DIR_DATA = string_make(s + 1);
break;
}

case 'e':
{
string_free(ANGBAND_DIR_EDIT);
ANGBAND_DIR_EDIT = string_make(s + 1);
break;
}

case 's':
{
string_free(ANGBAND_DIR_SAVE);
ANGBAND_DIR_SAVE = string_make(s + 1);
break;
}

#endif /* VERIFY_SAVEFILE */

default:
{
quit_fmt("Bad semantics in '-d%s'", info);
}
}
}
I need this to keep everyone's character dumps and pref files seperate from each other. The only I really need is "case u:", and some variants do indeed collapse the -d switch into just this case (NPPangband is the first example that springs to mind).

The usual purpose of the ANGBAND_PATH variable (still referred to as such in the main.c I apparently used last time) is specifying the lib folder and hence every subfolder not just the user folder. main_real in github's main.cc looks a lot like main in the main.c I have, but comes around 200 lines earlier.

Now I remember, I think I resorted to 2.3.6 before and then forgot that I had done so. That explains why kobold was complaining that there were still traps in the game.

I will need -duser=<path> or at least -d<path> command line switches to host it on live.

Gwarl August 9, 2018 13:31

for reference, this is NPP's far more concise handling of only the switch I need:

Quote:

/*
* Handle a "-d<what>=<path>" option
*
* The "<what>" can be any string starting with the same letter as the
* name of a subdirectory of the "lib" folder (i.e. "i" or "info").
*
* The "<path>" can be any legal path for the given system, and should
* not end in any special path separator (i.e. "/tmp" or "~/.ang-info").
*/
static void change_path(cptr info)
{
if (!info || !info[0])
quit_fmt("Try '-d<path>'.", info);

string_free(ANGBAND_DIR_USER);
ANGBAND_DIR_USER = string_make(info);
}
He didn't bother to update the comments

AnonymousHero August 11, 2018 18:29

Oh, yes, I see I did actually remove that -- it shouldn't be too much effort to bring it back, though.

Just curious... are you using the GCU/curses frontend or something else to handle the frontend for angband.live?

(I'm doing a... thing to the T2 codebase and if at all possible, I'd like to be able to remove curses. However, if angband.live needs it, then that might convince me to try harder to keep it. Still might get removed, obviously, but...)

Gwarl August 11, 2018 23:58

It is indeed the gcu port, that's my universal point of compatibility for all the variants. It would be a nightmare patching in the code to do anything else for each variant individually.

I have vague plans for some angband-specific javascript version of noteye in the future, which would then also solve graphics for every variant at once.

AnonymousHero August 12, 2018 08:31

Quote:

Originally Posted by Gwarl (Post 132745)
It is indeed the gcu port, that's my universal point of compatibility for all the variants. It would be a nightmare patching in the code to do anything else for each variant individually.

Yeah, that was what I was afraid of... :(

(What I've been experimenting with is basically completely gutting the Term subsystem and going towards supporting only an Allegro5-based frontend -- and hopefully Windows via cross-compilation, but that's a bit further off. The whole UI/keyboard subsystem is so unbelievably hackish and broken... :/ )

Quote:

Originally Posted by Gwarl (Post 132745)
I have vague plans for some angband-specific javascript version of noteye in the future, which would then also solve graphics for every variant at once.

I've actually been thinking of just doing away with the native GUI programming wholesale and changing T2 to just be a RESTful server and have a little bit of Javascript in the browser instead. It would be soooo much less painful.

(Just had a look at NotEye and it looks like even more hacks piled on top... it's kind of miraculous that such a monstrosity could even be made to work.)

t4nk August 12, 2018 20:28

Quote:

Originally Posted by AnonymousHero (Post 132750)
Yeah, that was what I was afraid of... :(

(What I've been experimenting with is basically completely gutting the Term subsystem and going towards supporting only an Allegro5-based frontend -- and hopefully Windows via cross-compilation, but that's a bit further off.

Why gut the Term, though?

Quote:

The whole UI/keyboard subsystem is so unbelievably hackish and broken... :/ )
IMO, there is nothing wrong with it conceptually. It's just a quality-of-implementation issue.

AnonymousHero August 13, 2018 17:09

Quote:

Originally Posted by t4nk (Post 132781)
Why gut the Term, though?


IMO, there is nothing wrong with it conceptually. It's just a quality-of-implementation issue.

I suppose most things could be argued to be quality-of-implementation, but it's a stretch in the T2 code base, at least. (No idea what you're using as a reference? Perhaps Vanilla...? I haven't actually looked into the vanilla code base, so these might not apply there. I'm guessing that it's at least vastly improved over T2 when the code base was modernized.)

Still, I'd argue that these are design problems:
  • The term code has one key queue per term, but requires that the active term be set to the first term (angband_term[0]) when 'interacting' with the keyboard queue, etc. The keyboard queue (singleton) should never have been tied to a term (multiple).
  • The handling of the UI event loop (singleton) is intermingled with the handling of each individual term. Again there's some nonsense where the current term must be set to the 0th one.
  • Generally speaking the "current term" is horrifically tangled into the code base all over the place. There should never have been such a thing as the "current term". (The concept doesn't really make sense.). This is the one that closest to a QoI issue, but I think it could be argued either way.

(I'm sure there's more that I'm forgetting right now.)

t4nk August 13, 2018 22:47

Quote:

Originally Posted by AnonymousHero (Post 132825)
I suppose most things could be argued to be quality-of-implementation, but it's a stretch in the T2 code base, at least. (No idea what you're using as a reference? Perhaps Vanilla...? I haven't actually looked into the vanilla code base, so these might not apply there. I'm guessing that it's at least vastly improved over T2 when the code base was modernized.)

Vanilla's ui-term.c is the same thing... To my knowledge, I was the only person since Ben Harrison to substantially change this thing :) The Term is indeed horribly written, but I think its fundamental ideas are sound.

Quote:

The term code has one key queue per term, but requires that the active term be set to the first term (angband_term[0]) when 'interacting' with the keyboard queue, etc. The keyboard queue (singleton) should never have been tied to a term (multiple).
True, and there is no reason why it must be like that. This is very easy to change, though.

Quote:

Generally speaking the "current term" is horrifically tangled into the code base all over the place. There should never have been such a thing as the "current term". (The concept doesn't really make sense.). This is the one that closest to a QoI issue, but I think it could be argued either way.
I'm not familiar with Allegro, but a quick look at the documentation suggests the standard pattern:
Code:

void al_set_target_bitmap(ALLEGRO_BITMAP *bitmap);
"This function selects the bitmap to which all subsequent drawing operations in the calling thread will draw to. To return to drawing to a display, set the backbuffer of the display as the target bitmap, using al_get_backbuffer. As a convenience, you may also use al_set_target_backbuffer."
That's how it's done in low level APIs (OpenGL, DirectX). Of course, it's not the only possible way of doing things, but it's pretty standard and it doesn't seem overly crazy to me.

When working on textui2, I came to the conclusion that it's useful to divide the Terms into two kinds; permanent (map, messages, sidebar, monster list) and temporary (inventory, options, knowledge menu - the stuff that goes away when the user presses ESC). Organizing temporary terms as a stack, with the top of the stack being the current target of rendering operations, is very convenient (and there were no problems with using this architecture while writing ncurses frontend). OTOH, permanent terms don't need to be on the stack.

I'm actually (very slowly) writing an Angband-insired roguelike (in D :)). So I've been thinking quite a bit about the architecture of the IO subsistem lately. The Term as an ADT (a two dimensional array of colored characters that keeps track of their updates since the last render) is surely worth keeping, and so is the stack of Terms. Anyway, hopefully you'll proceed with your ideas - I'm adding your TOME repo to bookmarks :)

AnonymousHero August 14, 2018 15:42

Quote:

Originally Posted by t4nk (Post 132834)
Code:

void al_set_target_bitmap(ALLEGRO_BITMAP *bitmap);
"This function selects the bitmap to which all subsequent drawing operations in the calling thread will draw to. To return to drawing to a display, set the backbuffer of the display as the target bitmap, using al_get_backbuffer. As a convenience, you may also use al_set_target_backbuffer."
That's how it's done in low level APIs (OpenGL, DirectX). Of course, it's not the only possible way of doing things, but it's pretty standard and it doesn't seem overly crazy to me.

... but in e.g. Allegro (which is obviously built on top of whatever the platform supports, in my case OpenGL) they do kind of the same, but there's actually a good reason for it, namely that all high-performance graphics APIs are done that way. Why? Well, graphics hardware functions very differently to a regular computer and you (the programmer) really need to be aware of that and think in terms of the underlying mechanism -- if you e.g. try to blit from several hundred character-sized textures to the display, then you're going to have a bad time. (What you must do is create a "font atlas" which contains all the characters and use that for blitting from. Etc. Generally speaking 'switching states' is slow on GPUs because of very high latency. You really just want to fill the pipeline.)

The problem is much lesser in programming graphics because the "display list" only sticks around for a single frame and then you start over. (Also known as "immediate mode".) For a game like Angband, that's pretty simple to manage because the scope is very limited -- I think the entirety of the code which does this in my T2 branch is about 50-100 lines? I'm pretty sure I can eventually get rid of the "damage" tracking that the term structure does -- leaving me with a simple 2D array of char+attribute... which might as well be inside the frontend code. (In fact the frontend code already has such a structure because I want it to be able to redraw without having to call back into the term code.)

Just to be clear: There are much better ways to manage the global drawing context which al_set_target_bitmap or whatever just hide under the carpet, such that you could actually have the compiler check your work, but they require pretty advanced type systems which C in the very least doesn't really support. They'd also get pretty hairy in C++, I imagine. Since most of the graphics APIs target C or C++, that's what we get.

Quote:

Originally Posted by t4nk (Post 132834)
When working on textui2, I came to the conclusion that it's useful to divide the Terms into two kinds; permanent (map, messages, sidebar, monster list) and temporary (inventory, options, knowledge menu - the stuff that goes away when the user presses ESC). Organizing temporary terms as a stack, with the top of the stack being the current target of rendering operations, is very convenient (and there were no problems with using this architecture while writing ncurses frontend). OTOH, permanent terms don't need to be on the stack.

Interesting -- I hadn't thought of doing it this way, but I think I'm going for a design where there's no "current target". All drawing methods must have an explicit target term where they will draw. (That will usually come from a formal function parameter, but obviously there will a top-level dispatching coming from the "window options", e.g. "what do I draw in which window".)

Quote:

Originally Posted by t4nk (Post 132834)
I'm actually (very slowly) writing an Angband-insired roguelike (in D :)). So I've been thinking quite a bit about the architecture of the IO subsistem lately. The Term as an ADT (a two dimensional array of colored characters that keeps track of their updates since the last render) is surely worth keeping, and so is the stack of Terms. Anyway, hopefully you'll proceed with your ideas - I'm adding your TOME repo to bookmarks :)

I'm not saying that the "2D grid" is a bad abstraction -- it's the intermingling of concerns of the event loop, drawing to the screen and keyboard input into one big ball of mud where it's really unclear what's responsible for what (and how 'many' there are of each).

I'm not convinced in any way that tracking "damage" at a single-character level is a useful thing -- just redraw from scratch for every frame[1]. An even reasonably modern GPU should be able to draw Angband at several hundred (if not thousands) of FPS.

(The exceptions here would be old frameworks where this type of drawing is not really supported very well. My experiences in SDL2.x and Allegro 5 suggest that at least there's no problem there.)

[1] Here's another mismatch between that UI code and the modern world. You really want do just draw on every frame (if there have been any changes) and the Angband/T2 code contains sleep, etc. in various places in the code. These could end up being pretty non-trivial to avoid because changing the structure around an event loop might end up being difficult... I'm not quite giving up yet because it might be reasonable to with coroutines or similar.

EDIT: Anyway, this is ranting at this point... :).

Nick August 14, 2018 23:17

Quote:

Originally Posted by t4nk (Post 132834)
When working on textui2,

Veering temporarily off-topic (sorry AH), I'm really sorry that is not incorporated in V yet - both takkaria and I have thought about it and got no further than that. I'm tempted to say I'll add that to the list of things for the next version...

AnonymousHero August 15, 2018 12:52

@Nick Heh, I think it's just descended into ranting at this point, so a break from that is nice :).

I definitely agree about textui2, btw. It looked really nice.

t4nk August 15, 2018 21:44

Quote:

I'm not saying that the "2D grid" is a bad abstraction -- it's the intermingling of concerns of the event loop, drawing to the screen and keyboard input into one big ball of mud where it's really unclear what's responsible for what (and how 'many' there are of each).
Well, one thing to note is that there are only two situations when the screen must be redrawn:
1) When the game is waiting for user input (so the user should see the latest state of the game)
2) When some animation is played

Overly frequent screen redraws is the number one cause of slowdowns in textui1 (and requires hacks to work around), since most displays can be redrawn no more than 60 times per second. Thus, there is some synchronization between handling events and drawing to the screen.

Quote:

I'm not convinced in any way that tracking "damage" at a single-character level is a useful thing -- just redraw from scratch for every frame[1]. An even reasonably modern GPU should be able to draw Angband at several hundred (if not thousands) of FPS.
It depends. SDL2's high-level API is too slow for that (and I did use font atlases - see main2-sdl2:make_font_cache()). You might also want to (eventually) write a frontend for terminal emulator using termbox or some such... Anyway, z-term.c's approach to that is a bit too complicated, I currently use
Code:


struct TermCell
{
    dchar codepoint = 0;
    RGBA foreground = Color.white;

    // Hack - the biggest codepoint is 0x10_FFFF, which is 21 bits;
    // that leaves 11 more bits in a dchar, which we use for bitflags.
    // The flags are used only in this module; don't forget to clear them.

private:

    enum _Mask : uint
    {
        dirty = 1 << 31,
        clear = 0x1F_FFFF,
    }

    TermCell dirty() const pure
    {
        return TermCell(this.codepoint | _Mask.dirty,
                        this.foreground);
    }

    TermCell clear() const pure
    {
        return TermCell(this.codepoint & _Mask.clear,
                        this.foreground);
    }

    bool isDirty() const pure { return this.codepoint & _Mask.dirty; }
    bool isClear() const pure { return (this.codepoint & _Mask.clear) == this.codepoint; }
}

Quote:

Veering temporarily off-topic (sorry AH), I'm really sorry that is not incorporated in V yet - both takkaria and I have thought about it and got no further than that. I'm tempted to say I'll add that to the list of things for the next version...
Well, ping me if you decide to do that :) I recall there were some updates to ui-display.c and some other things. Anyway, textui2 didn't go to waste after all - I'm now finding it useful for remembering how SDL2 works :)

Gwarl September 25, 2018 16:52

Bump. If we can get user directory command line arguments back this week, we'll have a competition next month.

AnonymousHero September 27, 2018 21:14

Quote:

Originally Posted by Gwarl (Post 133461)
Bump. If we can get user directory command line arguments back this week, we'll have a competition next month.

Unfortunately, I'm way too busy at the moment :(.

I've added an issue for now, though: https://github.com/tome2/tome2/issues/30

Cuboideb June 13, 2021 16:23

Hello, I have many requests for porting ToME to android. Do I need some kind of authorization from darkgod or the team that created 2.4.0 ? I wrote to darkgod in the tome 4 page and the forums, but got no response.

BTW, thank you for upgrading the code. It seems that you did a lot of work!

KesTheHammer October 1, 2021 13:32

Quote:

Originally Posted by Cuboideb (Post 153788)
Hello, I have many requests for porting ToME to android. Do I need some kind of authorization from darkgod or the team that created 2.4.0 ? I wrote to darkgod in the tome 4 page and the forums, but got no response.

BTW, thank you for upgrading the code. It seems that you did a lot of work!

Any chance of playing this through Termux?

I've played frog through Termux - but I am not a Linux user, so trying to figure out how to install it is beyond my capabilities.

fiery_mews October 1, 2021 17:10

Quote:

Originally Posted by KesTheHammer (Post 155602)
Any chance of playing this through Termux?

I've played frog through Termux - but I am not a Linux user, so trying to figure out how to install it is beyond my capabilities.

Yes, it works in Termux - IIRC I submitted a (very small) patch at one point to ensure this. For a while I regularly played ToME 2 on a Pixel C.

Edit: You'll want to install a compiler (probably clang), make, cmake, boost, and ncurses. (Be warned that boost takes up a LOT of space.) After that you can follow the build instructions on the Github page as usual. Note that some of the controls may be a bit hinky if you're used to the Win32 or X11 interfaces.


All times are GMT +1. The time now is 06:09.

Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2021, vBulletin Solutions Inc.