Jump to content
Shawn Jefferson

Atari Moria, testing needed!

Recommended Posts

I've got almost the entire Mines of Moria rogue-like game ported to the Atari, using VBXE and an Atarimax Flash 8Mbit cartridge. The only gameplay thing left to port is the "look" command. I will be adding joystick control, and a few other cosmetic things, and I will look into prerendering some levels and depacking from cartridge, as the random level generation is still around 30 seconds per level.

 

I would appreciate any testing and bug reports though! Especially when it comes to the various spells, prayers, wands, staffs and potions and monsters. '?' brings up the help screen. CTRL-W enters wizard mode, which lets you cheat. CTRL-directions work in Altirra too, so you can use your direction keys (for up, down, right and left anyway.)

 

A good page for Moria information:

http://beej.us/moria/

 

The cart image is an Atarimax 8Mbit old style banking (cart 42 in Altirra). You need VBXE. The current colors are set for PAL.

 

A couple of questions:

 

What about colors of objects? I have some objects colored white and some blue. I couldn't decide whether to color all objects blue or white... monsters are currently red, which I think works fine.

 

In some of the inventory screens there is a solid line below the inventory listing and in some there isn't. Which looks better?

 

I restored some of the things I had initially changed (the history of messages are at 20 now), but monster recall/memories are currently not implemented. They will take a lot of memory and further cartridge banking, which may slow the game a bit. Are they important to the game play or not? (old moria players this question is for you.)

 

Any questions or comments welcome.

 

AtariMoria_55_alpha2.bin

  • Like 6

Share this post


Link to post
Share on other sites

Never played Moria, and it's been a long time since I played NetHack:

 

post-16457-0-25965800-1428870015_thumb.png

 

It's a lot more playable than I would have expected, though.

 

The level generator seems to be spending some huge amount of time in a division routine at $136A. Might be able to speed it up.

 

Share this post


Link to post
Share on other sites

Thanks! There are still a few bugs, found one today when you max out your inventory.

That routine at $13xx is in the C runtime.... I'll check it out and see what I can do to optimize it a bit more. The random generator was never designed to run on a 1.79Mhz machine with only 64k. :)

 

update: using the profiler in your great emulator, Altirra, with my debug symbols loaded, it was easy to see that the function is the cc65 runtime udiv32, called by the random number generator that moria uses. This is a 32-bit pseudo random number generator, and I didn't want to touch it too much, since important parts of the game rely on it (for instance in a single game the town always looks the same because the seed is saved and always generates the same random numbers.)

 

It seems though that if I can replace this code with something faster on a 6502 it will really make a difference in the dungeon generator. Here's the code:

 

 

 

/* source/rnd.c: random number generator
   Copyright (c) 1989-92 James E. Wilson
   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. */
#include "config.h"
#include "constant.h"
#include "types.h"

/* Put into lowcode */
#pragma code-name("CODE")
#pragma rodata-name("RODATA")
#pragma data-name("DATA")
#pragma bss-name("BSS")

/* This alg uses a prime modulus multiplicative congruential generator
   (PMMLCG), also known as a Lehmer Grammer, which satisfies the following
   properties
   (i)  modulus: m - a large prime integer
   (ii)  multiplier: a - an integer in the range 2, 3, ..., m - 1
   (iii) z[n+1] = f(z[n]), for n = 1, 2, ...
   (iv)  f(z) = az mod m
   (v)  u[n] = z[n] / m, for n = 1, 2, ...
   The sequence of z's must be initialized by choosing an initial seed
   z[1] from the range 1, 2, ..., m - 1.  The sequence of z's is a pseudo-
   random sequence drawn without replacement from the set 1, 2, ..., m - 1.
   The u's form a psuedo-random sequence of real numbers between (but not
   including) 0 and 1.
   Schrage's method is used to compute the sequence of z's.
   Let m = aq + r, where q = m div a, and r = m mod a.
   Then f(z) = az mod m = az - m * (az div m) =
      = gamma(z) + m * delta(z)
   Where gamma(z) = a(z mod q) - r(z div q)
   and  delta(z) = (z div q) - (az div m)
   If r < q, then for all z in 1, 2, ..., m - 1:
   (1) delta(z) is either 0 or 1
   (2) both a(z mod q) and r(z div q) are in 0, 1, ..., m - 1
   (3) absolute value of gamma(z) <= m - 1
   (4) delta(z) = 1 iff gamma(z) < 0
   Hence each value of z can be computed exactly without overflow as long
   as m can be represented as an integer.
 */
/* a good random number generator, correct on any machine with 32 bit
   integers, this algorithm is from:
Stephen K. Park and Keith W. Miller, "Random Number Generators:
 Good ones are hard to find", Communications of the ACM, October 1988,
 vol 31, number 10, pp. 1192-1201.
   If this algorithm is implemented correctly, then if z[1] = 1, then
   z[10001] will equal 1043618065
   Has a full period of 2^31 - 1.
   Returns integers in the range 1 to 2^31-1.
 */
#define RNG_M 2147483647L  /* m = 2^31 - 1 */
#define RNG_A 16807L
#define RNG_Q 127773L    /* m div a */
#define RNG_R 2836L    /* m mod a */
/* 32 bit seed */
static int32u rnd_seed;
/* holds the previous rnd state */
static int32u old_seed;
 
int32u __fastcall__ get_rnd_seed(void)
{
  return rnd_seed;
}

void __fastcall__ set_rnd_seed(int32u seedval)
{
  /* set seed to value between 1 and m-1 */
  rnd_seed = (seedval % (RNG_M - 1)) + 1;
}

/* returns a pseudo-random number from set 1, 2, ..., RNG_M - 1 */
int32 __fastcall__ rnd(void)
{
  register long low, high, test;
  high = rnd_seed / RNG_Q;
  low = rnd_seed % RNG_Q;
  test = RNG_A * low - RNG_R * high;
  if (test > 0)
    rnd_seed = test;
  else
    rnd_seed = test + RNG_M;
  return rnd_seed;
}

/* change to different random number generator state */
void __fastcall__ set_seed(int32u seed)
{
  old_seed = get_rnd_seed();
  /* want reproducible state here */
  set_rnd_seed(seed);
}

/* restore the normal random generator state */
void __fastcall__ reset_seed(void)
{
  set_rnd_seed(old_seed);
}

/* Generates a random integer x where 1<=X<=MAXVAL -RAK- */
int __fastcall__ randint(int maxval)
{
  register long randval;

  randval = rnd ();
  return ((int)(randval % maxval) + 1);
}

 

 

 

PS. In the original Moria code, the random number generator is seeded from the clock, but since the Atari doesn't have a clock, I was using the RANDOM ($D20A). Is there any initialization that needs to be done first? I noticed that with Altirra at least, the code is not as random as I'd have thought (upon initially running the game... it's like it's generating the same seed from RANDOM deterministically, maybe due to power on state?)

Edited by Shawn Jefferson

Share this post


Link to post
Share on other sites

Ouch. Yeah, calling straight 32-bit mul/div routines is overkill for that routine. cc65 also may not be merging the divide and modulus operations to take advantage of division routines producing both.

 

Regarding RANDOM: this is a common mistake. On the real hardware, the value you get from RANDOM is fully deterministic in the number of machine cycles since the shift register was last initialized via SKCTL. This means that if you use it, you always want to have a nondeterministic delay in between the last reset and when you start pulling random numbers. People unintentionally tend to rely on the initial disk load for this, which is why they're surprised when they see this behavior in an emulator, but you can get the same effect with a cartridge start. The best solution is to wait for the user to press a key or button before pulling random numbers for the first time. As far as I know there is no other good source for this -- not even uninitialized memory will work, as the cold start pattern is actually quite deterministic.

  • Like 2

Share this post


Link to post
Share on other sites

Thanks! I quickly switched the rnd functions to use the 16-bit version supplied by the C runtime, and it looks, at least so far that it's about three times quicker and still provides what the game requires. I'm going to tidy it up a bit more and remove the not required int32 variables. The game only ever tries to generate an int16 anyway.

 

On the RANDOM front, I will add that into the project. I was going to put up a VBXE graphics title page anyway, so I'll wait for the user to press a key there and generate the seed after that! I figured it was something to do with power on state.

 

Update: Wow, removing that routine and going with a 16-bit one without all the divisions has seriously sped up the generation of dungeons, on average it only takes 2-3 seconds now. I think I can remove the "Generating level..." message even! It also speeds up other parts of the game slightly too, which is also nice.

 

I'll post another version when I have added joystick control.

Edited by Shawn Jefferson
  • Like 2

Share this post


Link to post
Share on other sites

Joystick control is a little more complicated that I had hoped, and I wanted to get this much faster dungeon generation version uploaded.

 

Level generation is in the order of 2-3 seconds (!) now, with the simple swap out of that random number generator. Also fixed:

 

- added a message if VBXE is not detected

- added bypass to boot if option is held at boot (to flash another image onto cart)

- added a line at the bottom of inventory and other message pop-ups.

- fixed a bug where you could pick up more items that you should have been able to (causing a crash or video corruption.)

 

 

AtariMoria_5.5alpha3.bin

  • Like 1

Share this post


Link to post
Share on other sites

Beta1 just posted on the blog, with a few screenshots.

 

http://atariage.com/forums/blog/18/entry-12012-beta1/

 

Game play is fully ported now. Highscores, monster memory, character and game are all being saved to flashcart. Highscores and monster memory persist across multiple games.

 

Give it a try and please report any bugs!

 

PS. Adding the cartridge image here too:

 

AtariMoria_55beta1.bin

Edited by Shawn Jefferson
  • Like 2

Share this post


Link to post
Share on other sites

Just curious - any particular reason this couldnt be done on the stock XE video? Youd need to use the 1/2 size char fonts which arent as pretty but I imagine it would work?

Share this post


Link to post
Share on other sites

Why not use RANDOM $D20A entirely in place of the software generator? Of course after user input delay.

As far as I have tested it is really good in terms of randomness and you can't beat it's speed :)

Share this post


Link to post
Share on other sites

Just curious - any particular reason this couldnt be done on the stock XE video? Youd need to use the 1/2 size char fonts which arent as pretty but I imagine it would work?

 

One reason is memory. I'm using the VBXE memory itself from $4000-9FFF to bank in the various structures. It would be much more complicated to do it only in the 16k extended memory bank, and add on top of that the memory it takes to do 80 columns in software. I don't think you could port the code and get the entire thing to fit, or at least it would be much more work.

 

I do plan on trying to get it working with 40 columns, extended memory and the flashcart only... but I will need to make changes to the game, eliminate some items for instance, and maybe re-arrange the screen layout slightly.

 

 

Why not use RANDOM $D20A entirely in place of the software generator? Of course after user input delay.

As far as I have tested it is really good in terms of randomness and you can't beat it's speed :)

 

Well as I said above, the game makes use of the PRNG to generate levels, unique towns, etc... I was worried that the game would either not be as true to the original code, or the ability to restore a seed and get the same random numbers wouldn't work.

  • Like 1

Share this post


Link to post
Share on other sites

Makes me want a VBXE :)

I'm running on Altirra. Worth it, it is a great port of a classic Roguelike. I kindda want a VBXE, but i'm lazy at the moment.

  • Like 1

Share this post


Link to post
Share on other sites

Atari Moria v55 beta2:

 

- added joystick control (joystick is only read if at least two vblanks have passed, which seems to provide the right feel.) Joystick button can be used for most any key prompts. Joystick button and direction digs a tunnel.

- fixed a few bugs, many are probably still there (report them if you see any!)

- added a pause at startup to get better randomization.

- added creating items to wizard mode (you'll need the source, or some of the information on Moria websites to do this properly.)

- added a player structure display to wizard mode (Ctrl-C), to aid in debugging.

- added the rest '*' command to rest until healed and mana restored

 

The game is playable and should even be able to be completed in the state it's in. It seems to work well with CPU accelerators (in Altirra anyway!)

 

PS. My hat's off to anyone who takes an original game or port and brings it past the finish line. Play testing and bug hunting at the 80%-90% done mark is absolutely not fun. Especially a game like Moria that can take hundreds of hours to finish, with so many items, monsters, and spells. :(

 

Game Requirements:

- VBXE

- AtariMax 8mb flashcart (currently old style banking, bank 127 active at boot.)

- 64k (uses RAM under the OS)

AtariMoria_55beta2.bin

Edited by Shawn Jefferson
  • Like 3

Share this post


Link to post
Share on other sites
...absolutely not fun.

 

Maybe it'd be a little more fun to test, and to play in general, if you started enhancing the graphics some at this point. icon_smile.gif Isn't that part of why you're using VBXE functions in the first place (for enhanced graphics), or are you just interested in the resolution/80-columns (which is of course a graphics enhancement itself)? What are the exact capabilities of this mode, is it any two colors per character region?

Edited by MrFish

Share this post


Link to post
Share on other sites

It's definitely for 80 columns... and extra memory. It's more difficult than it first appears to go from aacii to graphics with this game. Quite a bit needs to be changed.

 

At this point my to do list:

- finish the port

- convert to 40 columns and extended memory (losing some game elements due to lack of memory)

- look at adding graphics

Share this post


Link to post
Share on other sites

Hi Shawn.

 

It's great to see such progress in development, i'm really curious about joystick support. I tested Moria some time ago in Altirra, but would it be possible to compile the game as xex file, or in a way allowing to run it on real hardware (without Atarimax cart, eg using Side's SDX)?

 

Thank you and keep up the good work. It's really cool project and last item from your todo list: "look at adding graphics" is making it even more interesting ;).

 

Cheers,

W.

Share this post


Link to post
Share on other sites

Hi Shawn.

 

It's great to see such progress in development, i'm really curious about joystick support. I tested Moria some time ago in Altirra, but would it be possible to compile the game as xex file, or in a way allowing to run it on real hardware (without Atarimax cart, eg using Side's SDX)?

 

Thank you and keep up the good work. It's really cool project and last item from your todo list: "look at adding graphics" is making it even more interesting ;).

 

 

Unfortunately, it's not going to see any release that doesn't involve a cartridge format. The problem is that the game is too big. It was never designed to run in 64k, and trying to squeeze it down would mean changing the game from Moria into just a "rogue-like", and we already have those on the Atari.

 

Currently there is:

 

~ 24k for the cave itself

~ 14k for the monster tables

~ 24k for the object tables

~ 20k for the spell tables and other assorted tables/information

~ 50 x 8k banks with code (quite a bit of duplicated code to cut down bank switching)

 

oh, and the C runtime, some data and variables and all the banking functions and game save code is in RAM.

 

To squeeze it all in, I'm cheating. I'm using VBXE for the 80 column mode, and I'm using it's ability to overlay 32k of its ram at $4000. All the data is in VBXE ram and I'm banking that in depending if I'm accessing the cave, monster data, object data or spell/assorted data. Then all code is running out of the cartridge at $A000-BFFF with quite a bit of banking going on.

 

I do think it's possible to cut the game down slightly so that it runs with an Atarimax cartridge and extended memory ($4000-7FFF), without the VBXE. You can see that this will probably involve cutting some of the objects from the game (how many broken daggers do you need anyway? ;) ), and probably making the cave smaller too.

Edited by Shawn Jefferson

Share this post


Link to post
Share on other sites

I don't have a VBXE, but I have a RAM 576XE and wonder if a version that uses the extended memory on an expanded Atari could retain all the gameplay as the VBXE version, albeit with a 40-column display.

Share this post


Link to post
Share on other sites

I do think it's possible to cut the game down slightly so that it runs with an Atarimax cartridge and extended memory ($4000-7FFF), without the VBXE. You can see that this will probably involve cutting some of the objects from the game (how many broken daggers do you need anyway? ;) ), and probably making the cave smaller too.

 

No, it'd be disrespectful to all your work and the game itself. I'll buy the cart version ;).

 

Cheers,

W.

Share this post


Link to post
Share on other sites

Played a couple characters this weekend and like all my rogue-like experiences I made it to level 4-5'ish before being eaten by a grue. (kidding, I forget how I died)

 

I'm playing on Altirra though I burned the game on a Atarimax cart and verified that it did not work on my 800+Incog because, no VBXE.

 

I gotta say I love the game, please don't change the graphics, it's a rogue-like, the best are ASCII only anyways. If you can figure out a way to make a 40col version or a version that runs with software 80col drivers I'd love to play test further.

Share this post


Link to post
Share on other sites

Here's beta3... a few small bugs fixed and I decided to add some things to the game (don't worry, classic mode still available.) At this point I have added the Tavern and the Guild to the town level. More detail here:

http://atariage.com/forums/blog/18/entry-12569-beta3-added-two-buildings-to-the-town/

 

I wonder especially how the Guild might affect game play. Currently you have to be level 3 or higher to join, and it also costs 1000 gold, although a character less than level 3 is unlikely to have enough gold to join anyhow, so maybe that's an artificial constraint that doesn't add anything.

 

Still requires VBXE... haven't started the 40-column conversion, still planning what needs to be changed.

 

 

AtariMoria v55beta3.bin

  • Like 2

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...