The Return of Viking Chess (Hnefatafl)

Want to talks about games you like, would like to see developed on the Oric, it's here.
User avatar
Dbug
Site Admin
Posts: 4444
Joined: Fri Jan 06, 2006 10:00 pm
Location: Oslo, Norway
Contact:

Re: The Return of Viking Chess (Hnefatafl)

Post by Dbug »

You know, you could have a 'teacher' mode that shows hints to the player on what he should play/should avoid, perhaps drawing small numbers in the cells indicating recommended/advised locations, so players can learn to play :)
User avatar
barnsey123
Flight Lieutenant
Posts: 379
Joined: Fri Mar 18, 2011 10:04 am
Location: Birmingham

Re: The Return of Viking Chess (Hnefatafl)

Post by barnsey123 »

Dbug wrote:You know, you could have a 'teacher' mode that shows hints to the player on what he should play/should avoid, perhaps drawing small numbers in the cells indicating recommended/advised locations, so players can learn to play :)
500 bytes left... :?

Maybe in the disk version (TBD if I ever can) a menu in the loader will allow you to select three different programs "Play as King", "Play as Attackers" and "Tutorial"...here's hoping anyway...
User avatar
Dbug
Site Admin
Posts: 4444
Joined: Fri Jan 06, 2006 10:00 pm
Location: Oslo, Norway
Contact:

Re: The Return of Viking Chess (Hnefatafl)

Post by Dbug »

barnsey123 wrote:
Dbug wrote:You know, you could have a 'teacher' mode that shows hints to the player on what he should play/should avoid, perhaps drawing small numbers in the cells indicating recommended/advised locations, so players can learn to play :)
500 bytes left... :?

Maybe in the disk version (TBD if I ever can) a menu in the loader will allow you to select three different programs "Play as King", "Play as Attackers" and "Tutorial"...here's hoping anyway...
If you have all the code on SVN, I can take a look at the memory map and see if I can get the memory usage down :)
User avatar
barnsey123
Flight Lieutenant
Posts: 379
Joined: Fri Mar 18, 2011 10:04 am
Location: Birmingham

Re: The Return of Viking Chess (Hnefatafl)

Post by barnsey123 »

Dbug wrote:If you have all the code on SVN, I can take a look at the memory map and see if I can get the memory usage down :)
in v0.088 I've reduced the size of the prog from 37222 bytes to 36914 (saving about 300 bytes). This was a mixture of improving some inefficient routines and some loop unrolling.
All src is on SVN so yes, please take a look but only if you've got time.

There are two areas which definitely need changing, one is a clumsy text printing routine called "chasm2" in draw.s (see below), I've tried changing this with "chasm3" (commented out for now) which compiles OK but I get no text on the hires screen. The problem with chasm2 is I have to hardcode the locations for the start of the char. I just can't get this to work when loading a variable (see chasm3). Have tried all manner of things (either it doesn't compile, or I get nothing or I get garbage)
A while ago Chema mentioned using self-modifying code to achieve this. I read up on it and Voodoo made more sense, I just don't get it... :(

Code: Select all

_chasm2
.(
	lda _deadcurset+0 ; deadcurset is a hires screen location
	sta tmp1+0
	lda _deadcurset+1
	sta tmp1+1
	ldx #0
loop
	lda _textchar	; load the char id no into accumulator
	cmp #40			; is it an ( - DEFENDER
	beq chasmDEF
	cmp #41			; is it an ) - ATTACKER
	beq chasmATT
	cmp #65			; is it an A?
	beq chasmA
	cmp #66			; B?
	beq chasmB
	cmp #68			; D?
	beq chasmD
	cmp #69			; E?
	beq chasmE
	cmp #70			; F?
	beq chasmF
	cmp #71			; G?
	beq chasmG
	cmp #73			; I?
	beq chasmI
	cmp #75			; K?
	beq chasmK
	cmp #76			; L?
	beq chasmL
	cmp #79			; O?
	beq chasmO
	cmp #82			; R?
	beq chasmR
	cmp #83			; S?
	beq chasmS
	cmp #84			; T?
	beq chasmT
	cmp #85			; U?
	beq chasmU
	cmp #90			; Z?
	beq chasmZ
	lda $9900,x		; else print a space
chasmx2
	ldy #0
	sta (tmp1),y
	jsr _Add40
	inx
	cpx #7
	bcc loop
	rts
chasmDEF
	lda $9940,x
	jmp chasmx2
chasmATT
	lda $9948,x
	jmp chasmx2
chasmA
	lda $9A08,x
	jmp chasmx2
chasmB
	lda $9A10,x
	jmp chasmx2
chasmD
	lda $9A20,x
	jmp chasmx2
chasmE
	lda $9A28,x
	jmp chasmx2
chasmF
	lda $9A30,x
	jmp chasmx2
chasmG
	lda $9A38,x
	jmp chasmx2
chasmI
	lda $9A48,x
	jmp chasmx2
chasmK
	lda $9A58,x
	jmp chasmx2	
chasmL
	lda $9A60,x
	jmp chasmx2	
chasmO
	lda $9A78,x
	jmp chasmx2	
chasmR
	lda $9A90,x
	jmp chasmx2	
chasmS
	lda $9A98,x
	jmp chasmx2	
chasmT
	lda $9AA0,x
	jmp chasmx2	
chasmU
	lda $9AA8,x
	jmp chasmx2	
chasmZ
	lda $9AD0,x
	jmp chasmx2		
.)

;_chasm3
;.(
;	lda _deadcurset+0
;	sta tmp1+0
;	lda _deadcurset+1
;	sta tmp1+1
;	ldx #0
;loop	
;	lda _someint,x	; where someint represents say $9AD0 (for the char Z)
;	ldy #0
;	sta (tmp1),y
;	jsr _Add40
;	inx
;	cpx #7
;	bcc loop
;	rts	
;.)
Another area is when printing the message "Press a key" which occurs numerous times (I've tried putting it into a function but no luck getting it to work properly). I have to work on this some more as it's getting mixed up with some other output routines. I probably need to have seperate routines for lines 1-3 (of the bottom 3 text lines on a hires screen) I think I could save another 100-200 bytes if I can sort that one out.

A problem with making months-old code more efficient is it can introduce problems (I've been caught out before) for example: pseudocode:

Code: Select all

if (a==1) someroutine()
if (b==1) someroutine()
if (c==1) someroutine()
this could get "compressed" to the following:

Code: Select all

if ( (a==1) || (b==1) || (c==1))  someroutine()

This should result in shorter compiled code but - depending on what someroutine() does it may not be correct.
I may want someroutine() to run up to 3 times depending on the values a,b,c (not just once).
It's easy to get caught out...as they say: "logic is a method of arriving at the wrong answer with confidence..."
User avatar
Dbug
Site Admin
Posts: 4444
Joined: Fri Jan 06, 2006 10:00 pm
Location: Oslo, Norway
Contact:

Re: The Return of Viking Chess (Hnefatafl)

Post by Dbug »

There's a number of places where you suffer the 'death by a thousand cuts' problem.

For example you have:

Code: Select all

void checkincroute(){
  if ( players[a][b] == 0 ) 					incroute();
  if ( (a == 5) && (b == 5) && (players[a][b] == 4))	incroute();
  if (( piecetype == 3 )&&(tiles[a][b] == 4 ))	incroute(); // KING: corner square OK 
}
the incroute function is implemented in assembler this way:

Code: Select all

_incroute
	inc _route
	rts
Since '_route' is a normal variable the code will use absolute addressing, so the lenght of the function is 4 bytes (inc+2+rts)

The problem is that if you look at the generated code (%osdk%\tmp\linked.s) you will see that the compiler generated that:

Code: Select all

	ldy #0 
	jsr _incroute 
So basically for each call to this 4 bytes routine you get a 5 bytes function call, while if the 'inc _route' was directly inlined it would only take 3 bytes in total.

DrawPictureTiles() is a very simple function, yet it uses 16 bytes because the compiler kind of suck:

Code: Select all

_DrawPictureTiles
	lda #<(_PictureTiles) 
	sta _ptr_graph 
	lda #>(_PictureTiles) 
	sta _ptr_graph+1 

	ldy #0 
	jsr _drawtile 

	rts 
could be rewritten as:

Code: Select all

_DrawPictureTiles
	lda #<(_PictureTiles) 
	sta _ptr_graph 
	lda #>(_PictureTiles) 
	sta _ptr_graph+1 

	jmp _drawtile 
Which is 3 bytes shorter, but the problem is compounded by the fact that the compiler does not really generate code that uses the registers efficiently. A more efficient way would have been to have _drawtile takes two parameters (say X and Y) and have the code do:

Code: Select all

_DrawPictureTiles
	ldx #<(_PictureTiles) 
	ldy #>(_PictureTiles) 
	jmp _drawtile 
Which reduces the size globally because a function is called more than once, so for each additional call you reduce the size by two sta, which is 4 bytes here.

The whole 'chasmx' dispatcher can probably be reduced in size by replacing all the 'jmp chasmx2' by 'rts' and changing the original call to the dispatcher by a jsr followed by the 'chasmx2' function.

I can do some fixes, just not today.

So suggestions:
- Check the whole linked.s file, it gives a good overview
- Double check with the 'osdk_showmap.bat' to see what takes size
User avatar
barnsey123
Flight Lieutenant
Posts: 379
Joined: Fri Mar 18, 2011 10:04 am
Location: Birmingham

Re: The Return of Viking Chess (Hnefatafl)

Post by barnsey123 »

OK Dbug,

many thanks for that. I'm not sure I understand it all (still weak with ASM) but I've burnt through the C code and made some more improvements. Now down to 36732 so I have about 1K spare at present.

I'm going to make some more changes to slim it down further (I have some more routines to squeeze in and these will improve the AI). I must say I'm enjoying the play testing more as it's making smarter moves (but there's room for improvement...).
User avatar
barnsey123
Flight Lieutenant
Posts: 379
Joined: Fri Mar 18, 2011 10:04 am
Location: Birmingham

Re: The Return of Viking Chess (Hnefatafl)

Post by barnsey123 »

v0.090

More memory reductions, some improvements and a bug fix...the circled piece is the one selected for a possible move...note central square is not highlighted (it is possible to traverse it but not occupy it)
Showing bug fix for central square and new possible moves highlighting.
Showing bug fix for central square and new possible moves highlighting.
possiblemoves.png (20.89 KiB) Viewed 14637 times
Previously when pressing "P" for Possible Moves it still looked possible for a non-king piece to occupy the central square (in fact, you couldn't do this but it looked like you could). This is now fixed and so it should be less confusing for a new player.

There used to be a "compass" graphic printed instead of the new "red box". So I've saved some memory both in the code and in the graphics data. As a bonus it also looks better. 8)

If I can fit it in, I'll print a skull in dangerous locations...(but only in SAGA mode)
User avatar
Dbug
Site Admin
Posts: 4444
Joined: Fri Jan 06, 2006 10:00 pm
Location: Oslo, Norway
Contact:

Re: The Return of Viking Chess (Hnefatafl)

Post by Dbug »

I wanted to do some changes, but then I noticed there was a bunch of problems:
- the program does not switch to hires so all the screen is garbled
- when using the cursor to select the position that makes the screen to scroll
did I do something wrong? Is there something fancy to do with the 'loader' project?
User avatar
barnsey123
Flight Lieutenant
Posts: 379
Joined: Fri Mar 18, 2011 10:04 am
Location: Birmingham

Re: The Return of Viking Chess (Hnefatafl)

Post by barnsey123 »

Dbug wrote:I wanted to do some changes, but then I noticed there was a bunch of problems:
- the program does not switch to hires so all the screen is garbled
- when using the cursor to select the position that makes the screen to scroll
did I do something wrong? Is there something fancy to do with the 'loader' project?
Yes, the loader has to be loaded first (it sets hires and changes the font)
VIKLOAD.tap
Load this first
(5.32 KiB) Downloaded 442 times
This will display the loading picture and some text. When the picture turns red you have to type (blindly): CLOAD"VIKING.TAP"

IMPORTANT: Ensure VIKING.tap (main prog) is in the oricutron tapes directory (I have a bat file that copies the tap file there after building it)
User avatar
barnsey123
Flight Lieutenant
Posts: 379
Joined: Fri Mar 18, 2011 10:04 am
Location: Birmingham

Re: The Return of Viking Chess (Hnefatafl)

Post by barnsey123 »

v0.91
Fixed MAJOR bug in findpiece() routine. It's a "don't take a piece if it allows the king to escape" sort of thing.
It's not 100% fixed (about 90%) but I know what to do...
User avatar
Dbug
Site Admin
Posts: 4444
Joined: Fri Jan 06, 2006 10:00 pm
Location: Oslo, Norway
Contact:

Re: The Return of Viking Chess (Hnefatafl)

Post by Dbug »

By the way, if you are interested there's an easy way to get almost 1 kilobyte of free memory: Instead of using standard text, use alternate text, and overwrite the standard text with whatever you want :)
User avatar
Dbug
Site Admin
Posts: 4444
Joined: Fri Jan 06, 2006 10:00 pm
Location: Oslo, Norway
Contact:

Re: The Return of Viking Chess (Hnefatafl)

Post by Dbug »

Also, if you change SET OSDKADDR=$500 to say $400 in your osdk_config.bat, you get 256 more bytes available.
User avatar
barnsey123
Flight Lieutenant
Posts: 379
Joined: Fri Mar 18, 2011 10:04 am
Location: Birmingham

Re: The Return of Viking Chess (Hnefatafl)

Post by barnsey123 »

Dbug wrote:By the way, if you are interested there's an easy way to get almost 1 kilobyte of free memory: Instead of using standard text, use alternate text, and overwrite the standard text with whatever you want :)
Deffo interested but how would that work? I still have to load the new font data of size X. Presumably the method of loading would still be the same...so...I'm confused... :wink:
User avatar
barnsey123
Flight Lieutenant
Posts: 379
Joined: Fri Mar 18, 2011 10:04 am
Location: Birmingham

Re: The Return of Viking Chess (Hnefatafl)

Post by barnsey123 »

Dbug wrote:Also, if you change SET OSDKADDR=$500 to say $400 in your osdk_config.bat, you get 256 more bytes available.
Again confused...if I can set it to $400 why not $100 or less? I didn't get the whole Osdkaddr thing anyway...what is its purpose?
User avatar
Dbug
Site Admin
Posts: 4444
Joined: Fri Jan 06, 2006 10:00 pm
Location: Oslo, Norway
Contact:

Re: The Return of Viking Chess (Hnefatafl)

Post by Dbug »

barnsey123 wrote:
Dbug wrote:By the way, if you are interested there's an easy way to get almost 1 kilobyte of free memory: Instead of using standard text, use alternate text, and overwrite the standard text with whatever you want :)
Deffo interested but how would that work? I still have to load the new font data of size X. Presumably the method of loading would still be the same...so...I'm confused... :wink:
I'm assuming that you loaded the font in your Loader, so it's not present when the main code is present.
So assuming your loader is copying the font to the address $B400/$9800, which is where the STANDARD font is located.
Instead you could copy the font data to the address $B800/$9C00, which is where the ALTERNATE (the one shown in LORES 1 mode) is located.

That means that the whole standard charset area is available for your own code or data, of course if you try to print any text it's going to be garbled, but it's just a matter of using the attribute 9 at the start of the line, and there you go: You are using the second charset instead.
barnsey123 wrote:Again confused...if I can set it to $400 why not $100 or less? I didn't get the whole Osdkaddr thing anyway...what is its purpose?
This defines the address at which your code is assembled and loaded.
By default in the OSDK I set it to $500 because that makes the code compatible with the system DOS.

Since you are first releasing a floppy version, you can assemble as low as $400, that would trash the DOS if you tried to load the game from disk, but that gives you 256 more bytes.

You can't go lower, because the page 3 is used for I/O, page 1 is the stack, page 0 is where all your temporaries are stored.

Technically you can use the page 2 for whatever you want, but for that you need to not use the ROM at all, else things will crash badly :)
Post Reply