Page 3 of 3

Re: A Futile Exercise: C Roguelike in <4Kb

Posted: Sun Dec 17, 2023 8:55 pm
by GinDiamond
Interesting! I'll test the build out...

**EDIT**
Wow!! It trimmed off around 20 bytes for just 3 variables, I'll take a look at the cc65 readme for the zeropage variables...iirc you get 6 of them but perhaps a register keyword "suggests" to use it, I may do it explicitly...I know there's a way to increase/decrease your zeropage variable allocation size...

Re: A Futile Exercise: C Roguelike in <4Kb

Posted: Tue Dec 19, 2023 3:05 am
by GinDiamond
The *working* binary is now 1522 bytes!!!
I'm really trying to get this *finished* by this Thursday, but between changing jobs, the holidays, and finishing this current job demo, its pretty tight. I just need to get combat done and add in a status bar bit. Then, the original goal would've been hit! I then want to add xp, gold, and maybe a very very small level generator if possible!
There's a very interesting idea of making the map a multiple of 8 wide, then I could use bytes and bits to mark floors and walls! Items would be interesting, but I could make an item map to be overlaid on top of that I suppose (printMap and then printItems?)

Here's the code. But I have a GLARING ERROR

Code: Select all

/* ------------------
   Roguelike for Sym-1
   Patrick Jackson
   ------------------
*/

#include "symRogue.h"

#define ROW_LEN		16
#define	COL_HGHT	10
#define	MAP_SIZE	ROW_LEN * COL_HGHT
#define ROW_MASK    ( ROW_LEN - 1 )
#define MONS_NUM    3

unsigned char map[ MAP_SIZE ];

#if SYM==1
#pragma bss-name (push,"ZEROPAGE")
unsigned char lpos, direction, glyph, pos, hp, m_i;
#pragma bss-name (pop)
#else
unsigned char lpos, direction, glyph;
unsigned char pos;
unsigned char hp;
unsigned char m_i;
#endif

unsigned char mons_xy[MONS_NUM];
unsigned char mons_ch[MONS_NUM];
unsigned char mons_hp[MONS_NUM];

unsigned char key_input = 0x00;

void printMap()
{
    unsigned char i;

    clrscr();

    for ( i = 0; i < MAP_SIZE; ++i )
    {
        putchar( map[ i ] );
        if ( ! ( ( i + 1 ) & ( ROW_MASK ) ) )
        {
            newline();
        }
    }
}

void chkMCmbt()
{
    //
}

void chkPCmbt()
{
    mons_hp[ m_i ] -= (unsigned char)10;
    printf("Monster: %d\tHP: %d\n", m_i, mons_hp[ m_i ]);
}

unsigned char move()
{
    unsigned char _lpos;

    /* Move character around */
    _lpos = lpos;
    map[ _lpos ] = '.';

    switch ( direction )
    {
    case 'w': case 0:
        _lpos -= ROW_LEN;
        break;
    case 'a': case 1:
        _lpos--;
        break;
    case 's': case 2:
        _lpos += ROW_LEN;
        break;
    case 'd': case 3:
        _lpos++;
    default:
        break;
    }

    /* Check for wall, player, or monster collision */
    if (map[_lpos] == '#')
        _lpos = lpos;
    else if ( (glyph == '@') && (map[_lpos] == 'M'))
    {
        chkPCmbt();
        _lpos = lpos;
    }
    else if (map[_lpos] == '@')
    {
        chkMCmbt();
        _lpos = lpos;
    }
    map[_lpos] = glyph;

    return _lpos;
}

int main()
{
    /* Set up player pos */
    pos = 25;

    for ( m_i = 0; m_i < MONS_NUM; ++m_i )
    {
        mons_xy[ m_i ] = 50;
        mons_hp[ m_i ] = 50;
    }


    clrdraw();

    /* --------- Create map ---------
       Fill entire grid with wall tiles '#' */
    memset( map, '#', MAP_SIZE );
    /* Fill interior with floor tiles '.' */

    for ( m_i = ROW_LEN + 1; m_i < MAP_SIZE - ROW_LEN; m_i += ROW_LEN )
        memset( map + m_i, '.', ROW_LEN - 2 );

    /* --------- Main loop ----------- */
    do
    {
        lpos = pos;
        direction = key_input;
        glyph = '@';
        pos = move();
        for ( m_i = 0; m_i < MONS_NUM; ++m_i )
        {
            lpos = mons_xy[ m_i ];
            direction = rand()  & 0x03;
            glyph = 'M';
            mons_xy[ m_i ] = move();
        }
        printMap();
        key_input = input();
    }
    while ( key_input != 'q' );

    return 0;
}
If I hit a monster, its HP will jump to say, something even like 90 or like 102 or something crazy. I have mons_hp being set to 50, and the combat to be -=10, as an unsigned char. What is possibly happening?

Re: A Futile Exercise: C Roguelike in <4Kb

Posted: Tue Dec 19, 2023 3:36 am
by gfoot
GinDiamond wrote:
Interesting! I'll test the build out...

**EDIT**
Wow!! It trimmed off around 20 bytes for just 3 variables, I'll take a look at the cc65 readme for the zeropage variables...iirc you get 6 of them but perhaps a register keyword "suggests" to use it, I may do it explicitly...I know there's a way to increase/decrease your zeropage variable allocation size...
You can put as many globals in zero page as you can fit, in this way. It's different to the "register" keyword which causes local variables to use some of the few locations set aside for that. "register" is a double-edged sword and can be detrimental.
GinDiamond wrote:
If I hit a monster, its HP will jump to say, something even like 90 or like 102 or something crazy. I have mons_hp being set to 50, and the combat to be -=10, as an unsigned char. What is possibly happening?
In chkPCmbt you are harming a monster by index m_i but this will always be set to 3, beyond the range of the array, because this is called from outside the monster loop. You probably want to put a second monster loop inside chkPCmbt to loop over the monsters and work out which one the player actually hit, and then harm that one.

Re: A Futile Exercise: C Roguelike in <4Kb

Posted: Tue Dec 19, 2023 4:06 pm
by GinDiamond
I'll see what I can do, experiments last night led nowhere but I was super tired XD

Re: A Futile Exercise: C Roguelike in <4Kb

Posted: Tue Mar 12, 2024 4:26 am
by GinDiamond
Well, after alot of silence, I am rewriting this program! It's also on git:
https://github.com/ProgrammingCube/SymRogue

I had played around with optimization, and I got it down to around 1.5kb before the rewrite, but adding in combat was proving to be such a hassle! Also, I had optimized it so much it was hard for me to figure out what was going on.

Right now, its ~2.5kb in size. I have hooks in there for combat, then after combat I want to add the status bar. Then, I want to add in possible "generation" insofar as to make pillars/small rooms generate in, I think I can do this fairly easily.

THEN, I will optimize and optimize hard!

Please go take a look!

Re: A Futile Exercise: C Roguelike in <4Kb

Posted: Tue Mar 12, 2024 4:57 am
by GARTHWILSON
GinDiamond wrote:
I had played around with optimization, and I got it down to around 1.5kb before the rewrite
It seems like there's always more you can do to optimize for speed, size, or both; for example, where you have

Code: Select all

        lda     M0002
        beq     L001E
        cmp     #$01
        beq     L001F
        cmp     #$02
        beq     L0020
        cmp     #$03
        beq     L0021
        bra     L0008

you could save a byte for each comparison by decrementing A instead:

Code: Select all

        LDA  M0002
        BEQ  L001E
        DEA
        BEQ  L001F
        DEA
        BEQ  L0020
        DEA
        BEQ  L0021
        BRA  L0008

since after this, you're overwriting what was in A anyway.

Quote:
Also, I had optimized it so much it was hard for me to figure out what was going on.

Macros to the rescue!  And whether you do dabble in them or go hog-wild, do at least do plenty of commenting, separate sections with blank lines, indent loops, etc..

Re: A Futile Exercise: C Roguelike in <4Kb

Posted: Tue Mar 12, 2024 5:48 am
by GinDiamond
GARTHWILSON wrote:
GinDiamond wrote:
I had played around with optimization, and I got it down to around 1.5kb before the rewrite
It seems like there's always more you can do to optimize for speed, size, or both; for example, where you have

Code: Select all

        lda     M0002
        beq     L001E
        cmp     #$01
        beq     L001F
        cmp     #$02
        beq     L0020
        cmp     #$03
        beq     L0021
        bra     L0008

you could save a byte for each comparison by decrementing A instead:

Code: Select all

        LDA  M0002
        BEQ  L001E
        DEA
        BEQ  L001F
        DEA
        BEQ  L0020
        DEA
        BEQ  L0021
        BRA  L0008

since after this, you're overwriting what was in A anyway.

Quote:
Also, I had optimized it so much it was hard for me to figure out what was going on.

Macros to the rescue!  And whether you do dabble in them or go hog-wild, do at least do plenty of commenting, separate sections with blank lines, indent loops, etc..
Very intruiging!
It looks like assembly could be really handy, however I do want this to try and stay as "hand edited" free as possible, so all optimizations *should* be done in the C compiler/C code. I'll take a look though....


Also, combat works! It works better than it ever did, and much easier to read. 2,594 bytes too! And not even well optimized!

Re: A Futile Exercise: C Roguelike in <4Kb

Posted: Tue Mar 12, 2024 6:03 am
by GinDiamond
Sweeet, headed to bed! I got combat working and a very rudimentary status message! Only 3.232kB!!!

Now, I'll go back and look closlier at how to optimize the status message. I also have one feature to add before this is "done" as I wanted it...monster AI! I know it can't be grandiose, but I need something!!!

Please take a look! It builds both on Windows and your Synertek SYM-1, so, please, test it out and play with it!

https://github.com/ProgrammingCube/SymRogue/tree/main

I want to add the monster AI in, then I will be "done"! However, I'm never done....
I want to optimize this as far as it will go, and be able to add things in like "room generation", possibly items, or even different monsters!

Re: A Futile Exercise: C Roguelike in <4Kb

Posted: Tue Mar 12, 2024 9:56 pm
by GinDiamond
Yeah, I'm trying to figure out how to do a very small monster AI. I just need this feature, then its "done"!!!
https://youtu.be/rcGd2CN1V48

Re: A Futile Exercise: C Roguelike in <4Kb

Posted: Thu Mar 21, 2024 4:17 am
by GinDiamond
Big things happening... the game may be done tonight!

Re: A Futile Exercise: C Roguelike in <4Kb

Posted: Thu Mar 21, 2024 4:31 am
by GinDiamond
Hooray! SymRogue is "complete", at 3.454kb!!!!!

The code and build has been pushed to GitHub

Please note that as of this exact posting, there is a bug where the monster you're fighting may disappear from view. I'm sure its just a code ordering problem, I'm investigating it now.

Re: A Futile Exercise: C Roguelike in <4Kb

Posted: Thu Mar 21, 2024 6:16 am
by barnacle
That's not a bug! Invisible monsters are obviously an advanced feature :mrgreen:

Neil

Re: A Futile Exercise: C Roguelike in <4Kb

Posted: Sat Mar 23, 2024 2:34 pm
by GinDiamond
I think the bug is fixed! I think it was a signed char vs unsigned char problem.

The code is pushed, so now I will work on optimization! Get it down small as possible, and then try and cram in room generation!

Edit:
Nope! Still there! I may need a hand on figuring out why this is happening

UPDATE:
It seems that this is an age old problem, I'm drawing the monsters as I update them! If monster 4 is dead, but monster 2 isn't and moves on top of monster 4, not only is the corpse drawn on top of the monster, the next turn, the corpse disappears, and the next turn, the corpse reappears!

Re: A Futile Exercise: C Roguelike in <4Kb

Posted: Sat Mar 23, 2024 4:37 pm
by GinDiamond
It's done! Monsters work now!

The build is 3.448kB in size!

I will now look into optimization and floor generation!