As a French person I feel like it's my duty to explain strikes to you. - AdrienIer

Create an account  

 
Caster of Magic Release thread : latest version 6.06!

Yes, I accidently zipped save2.gam instead of SAVE2.GAM.


Attached Files
.zip   save2.zip (Size: 24.55 KB / Downloads: 2)
Reply

Yes, it seems to crash on yellow's turn. If I remove the ship movement assignment there is no crash. However it's strange. Ship movement assignment happens after spellcasting but when the game does crash yellow doesn't cast a spell. It feels like red messes something up which causes yellows turn to fail.
Disabling the instant disembark on movement feature still results in the crash so the bug is likely in assigning the movement. Unfortunately I don't have enough time right now to try fixing that, and won't be at home tomorrow so it'll have to wait until Monday.

In the unlikely case someone can do it faster, this is the current source code for that part :

Code:
;*=E60B6
.org 0EE6h
jmp start

overlanddistance:
push 3Ch
push ax
push bx
push cx
push dx
db 9Ah,48h,01,0B8h,00
add sp,0Ah
retn

getcity:
mov     ax, di
mov     dx, 72h ; 'r'
imul    dx
les     bx, [9CBCh]
add     bx, ax
retn

getoverland:
push cx
mov     cl, 5
shl     ax, cl
les     bx, [9EC2h]
add     bx, ax
pop cx
retn

getunittype:
mov     al, es:[bx+5]
mov     ah, 0
mov     dx, 24h ; '$'
imul    dx
mov     bx, ax
retn

loadposition:
mov ax,[bp-22h]
add ax,[bp-6]      ; Y
dec ax
mov cx,[bp-20h]
add cx,[bp-4] ; X
dec cx
retn

getcontinentID:
push ax
mov     ax, [bp+8]
mov     dx, 960h
imul    dx
les     bx, [9CD0h]
add     bx, ax
pop ax
mov     dx, 3Ch ; '<'
imul    dx
add     bx, ax
add     bx, cx
mov     al, es:[bx]
retn

getstackstrength:
mov     bx, [bp+8]
shl     bx, 1
shl     bx, 1
les     bx, [bx-636Ch]
mov     dx, 3Ch ; '<'
imul    dx
add     ax, cx
shl     ax, 1
add     bx, ax
mov ax,word ptr es:[bx]
and ax,03FFFh
add bx,12C0h
mov dx,word ptr es:[bx]
retn

getcontinenttype:
mov     ax, [bp+8] ; Plane
mov     dx, 384h
imul    dx
push    ax
mov     ax, [bp+6] ; Wizard
mov     dx, 0B4h ; '´'
imul    dx
pop     bx
add     bx, ax
mov     al, [bp-8] ; Contnent ID
cbw
add     bx, ax
mov al, byte ptr [bx-76F8h]
retn

get7050:
mov     bx, [bp+8] ; Plane
shl     bx, 1
mov     bx, [bx-7050h]
mov     dx, [bp+6] ; Wizard
shl     dx, 1
add     bx, dx
mov     ax, [bx]
retn

get7054:
mov     bx, [bp+8] ; Plane
shl     bx, 1
mov     bx, [bx-7054h]
mov     dx, [bp+6] ; Wizard
shl     dx, 1
add     bx, dx
mov     ax, [bx]
retn

alldone:
pop     di
pop     si
mov     sp, bp
pop     bp
retf

start:
push    bp
mov     bp, sp
sub     sp, 66h
push    si
push    di
;==========================================
; Shippoints initialize
;==========================================
xor     di, di
nextshippoint1:
mov     bx, di
shl     bx, 1
lea     ax, [bp-54h] ; Needed capacity
add     bx, ax
mov     word ptr [bx], 9
inc     di
cmp di,0Fh
jl nextshippoint1
;==========================================
; Shippoints, mark already fulfilled
;==========================================
xor si,si
nextunit2:
cmp si,[0BD92h]
jge shippointsdone
mov ax,si
call getoverland
mov [bp-56h],bx

mov     al, es:[bx+3]
cbw
cmp     ax, [bp+6] ; Wizard ID
jnz nextunit

mov     al, es:[bx+2]
cbw
cmp     ax, [bp+8] ; Plane
jnz nextunit

xor di,di
nextshippoint2:
cmp di,[9096h]
jge nextunit

mov     bx, di
shl     bx, 1
mov     ax, [bx-6F68h]
cmp     ax, [bp+8] ; Plane
jnz     nextshippoint3

mov     cx, [bx-6F2Ch]
mov     dx, [bx-6F4Ah]
mov     bx, [bp-56h]
mov     al, es:[bx]
cbw
cmp     ax, cx
jnz     short loc_ECD10
mov     al, es:[bx+1]
cbw
cmp     ax, dx
jnz     short loc_ECD10
jmp foundmatch
loc_ECD10:
mov     al, es:[bx+9]
cbw
cmp     ax, cx
jnz     nextshippoint3
mov     al, es:[bx+0Ah]
cbw
cmp     ax, dx
jnz     nextshippoint3    
cmp     byte ptr es:[bx+0Bh], 3
jnz     nextshippoint3
foundmatch:
call getunittype
mov     al, [bx+1B0h]
cbw
inc     ax
mov     bx, di
shl     bx, 1
lea     dx, [bp-54h]
add     bx, dx
sub     [bx], ax  ; Subtract capacity plus one more for the ship itself.
jg nextshippoint3
; Shippoint no longer requires any capacity : clear from list
mov     bx, di
shl     bx, 1
mov     word ptr [bx-6F68h], 0FFFFh


nextshippoint3:
inc di
jmp nextshippoint2


nextunit:
inc si
jmp nextunit2


shippointsdone:
;=========================================
; Get stacks on sea
;=========================================
push [bp+8]
push 0
push [bp+6]
push cs
call GetStacks
add sp,6


;=========================================
;=========================================
;=========================================
; Process all stacks
;=========================================
;=========================================
;=========================================
xor si,si
nextstack:
cmp si,[9D4Ah]
jge alldone

;=========================================
; Stack content analysis
;=========================================

mov word ptr [bp-16h],0 ; Ships in stack
mov word ptr [bp-18h],1 ; Ships only in stack
mov word ptr [bp-1Ah],0 ; Settlers in stack
mov word ptr [bp-32h], 0 ; Going unit in stack

les     bx, [9E8Ch]
add     bx, si
mov     al, es:[bx]
cbw
mov     [bp-12h], ax ; Stack # of units
les     bx, [9E9Ch]
add     bx, si
mov     al, es:[bx]
cbw
mov     [bp-20h], ax ; Stack Pos X
les     bx, [9E98h]
add     bx, si
mov     al, es:[bx]
cbw
mov     [bp-22h], ax ; Stack pos Y

xor di,di
nextunit4:
mov ax,di
call getoverland
mov     al, es:[bx]
cbw
cmp     ax, [bp-20h]
jnz nextunit5
mov     al, es:[bx+1]
cbw
cmp     ax, [bp-22h]
jnz nextunit5
mov     al, es:[bx+2]
cbw
cmp     ax, [bp+8]
jnz nextunit5

call getunittype
cmp     byte ptr [bx+1B0h], 0
jle notship1
mov word ptr [bp-16h],1 ; found ship
jmp gocheck
notship1:
mov word ptr [bp-18h],0 ; found nonship
test    word ptr [bx+1BAh], 20h
jz gocheck
mov word ptr [bp-1Ah],1 ; Found settler
gocheck:
mov ax,di
call getoverland
cmp     byte ptr es:[bx+0Bh], 3
jnz nextunit5
mov word ptr [bp-32h],1
nextunit5:
inc di
cmp di, [0BD92h]
jl nextunit4

cmp word ptr [bp-16h],1 ; Stack has no ships in it, this procedure doesn't deal with those
jnz nextstack2

cmp word ptr [bp-18h],1
jnz stackistransport

;=========================================
; Stack contains ships only
;=========================================

; find nearest shippoint
mov  word ptr [bp-8], 2710h  ; Closest distance
xor     di, di

nextshippoint6:
cmp di,[9096h]
jge shippointsdone2

mov     bx, di
shl     bx, 1
mov     ax, [bx-6F68h]
cmp     ax, [bp+8] ; Plane
jnz nextshippoint5

mov     bx, di
shl     bx, 1
mov ax, word ptr [bx-6F4Ah]
mov     bx, di
shl     bx, 1
mov bx, word ptr [bx-6F2Ch]
mov cx, [bp-22h]
mov dx, [bp-20h]
call overlanddistance

cmp ax,[bp-8]
jge nextshippoint5
mov [bp-8],ax

mov     bx, di
shl     bx, 1
mov     ax, [bx-6F2Ch]
mov     [bp-4], ax ; Target Shippoint X
mov     bx, di
shl     bx, 1
mov     ax, [bx-6F4Ah]
mov     [bp-6], ax ; Target Shippoint Y
mov     [bp-2Ch], di ; Target Shippoint ID

nextshippoint5:
inc di
jmp nextshippoint6


shippointsdone2:
cmp word ptr [bp-8], 2710h
jl sendtoshippoint
call ShipAttackTarget   ; If ship is not required, attack targets or perform idle movement
jmp sendto2

sendtoshippoint:
mov     bx, [bp-2Ch]  ; Target Shippoint ID
shl     bx, 1
lea     ax, [bp-54h]
add     bx, ax
mov     ax, [bx]
mov     [bp-2Eh], ax ; Capacity needed for this shippoint
sendto2:

mov word ptr     [bp-28h], 0
sendloop1:
mov     ax, [bp-28h]
cmp     ax, [bp-12h] ; Stack total units
jge     donesending

cmp word ptr     [bp-2Eh], 0
jle donesending
mov     bx, si
mov     cl, 2
shl     bx, cl
les     bx, [bx-62B4h]
mov     ax, [bp-28h]
shl     ax, 1
add     bx, ax
mov     ax, es:[bx]
mov     [bp-2Ah], ax
mov     ax, [bp-2Ah]
call getoverland
call getunittype
mov     al, [bx+1B0h]
cbw
inc     ax
sub     [bp-2Eh], ax ; Subtract transport capacity from shippoint required capacity

push    [bp-28h] ; Indexinstack
push    si    ; StackID
push    [bp-6]    ; Shippoint PosY
push    [bp-4]    ; Shippoint PosX
push    [bp-2Ah]
nop
push    cs
call    Assignmovement
add     sp, 0Ah
inc word ptr  [bp-28h]
jmp sendloop1

donesending:
mov     bx, [bp-2Ch]
shl     bx, 1
lea     ax, [bp-54h]
add     bx, ax
mov     ax, [bp-2Eh]
mov     [bx], ax       ; Store required capacity for shippoint
cmp ax,0
jg nextstack2
mov     bx, [bp-2Ch]
shl     bx, 1
mov     word ptr [bx-6F68h], 0FFFFh ; Clear shippoint if no more needed
jmp nextstack2

;=========================================
; Stack is transporting units
;=========================================

stackistransport:

cmp word prt [bp-32h],0 ; A unit already had a going order. do not move stack until it leaves (probably impossible situation in the current system)
jnz nextstack2

;=========================================
; Check all adjacent tiles for land
;=========================================

call tileaction

cmp word ptr [bp-0Ch],0FFFFh
jz movetotargetcontinent

;=========================================
; Disembark if able
;=========================================

xor di,di
nextunit8:
cmp di,[bp-12h]
jge nextstack2

mov     bx, si
mov     cl, 2
shl     bx, cl
les     bx, [bx-62B4h]
mov     ax, di
shl     ax, 1
add     bx, ax
mov     ax, es:[bx]
mov [bp-2Ah],ax
call getoverland
call getunittype
cmp     byte ptr [bx+1B0h], 0
jle x1x1
push    di
push    si
push    [bp-2Ah]
push    cs
call    RemoveFromStack
add     sp, 6
jmp nextunit7
x1x1:
push    di
push    si
push    [bp-0Eh]
push    [bp-0Ch]
push    [bp-2Ah]
push    cs
call    AssignMovement
add     sp, 0Ah
nextunit7:
inc di
jmp nextunit8

;==================================================
; Not near a destination continent, move there!
;==================================================
movetotargetcontinent:

cmp word ptr [bp-1Ah],1
jz issettler2
do7050instead:
mov word ptr [bp-1Ah],0   ; No settling continent, pretend we have no settler
call get7050
jmp movetothiscontinent
issettler2:
call get7054
or ax,ax
jz do7050instead

movetothiscontinent:
or ax,ax     ; no 7050 continent, nowhere to go!!!
jz nextstack2

; Find
mov ax,[bp-22h]
mov cx,[bp-20h]
mov [bp-26h],ax ; Out current position
mov [bp-24h],cx

mov word ptr [bp-1Ch],0FFFFh ; best unload position X (land)
mov word ptr [bp-1Eh],0FFFFh ; best unload position Y
mov word ptr [bp-2Ah],0FFFFh ; best unload position X (sea)
mov word ptr [bp-2Ch],0FFFFh ; best unload position Y
mov word ptr [bp-14h],08888h ; best unload position priority

mov word ptr [bp-22h],0
nexty2:
mov word ptr [bp-20h],0
nextx2:

mov ax,[bp-22h]
mov cx,[bp-20h]
call getstackstrength
or ax,ax
jnz nexttile3

call tileaction
cmp word ptr [bp-0Ch],0FFFFh
jz nexttile3
; We found a tile where we can disembark
cmp word ptr [bp-1Ah],1
jz issettler5
mov ax,[bp-26h] ; Closest to our current location is best
mov bx,[bp-24h]
mov cx,[bp-0Eh]
mov dx,[bp-0Ch]
jmp distprio

issettler5:
mov     bx, [bp+8]
shl     bx, 1
mov     bx, [bx-7062h] ; Settler selected destination shore tile
mov     ax, [bp+6]
shl     ax, 1
add     bx, ax
mov ax,[bx]
push ax
mov     bx, [bp+8]
shl     bx, 1
mov     bx, [bx-7066h]
mov     ax, [bp+6]
shl     ax, 1
add     bx, ax
mov bx,[bx]
pop ax
mov cx,[bp-0Eh]
mov dx,[bp-0Ch]
distprio:
call overlanddistance
mov cx,200
imul cx
mov cx,[bp-10h]
sub cx,ax
mov ax,cx
cmp ax,[bp-14h]
jle nexttile3
mov [bp-14h],ax
mov ax,[bp-0Ch]
mov [bp-2Ah],ax
mov ax,[bp-0Eh]
mov [bp-2Ch],ax
mov ax,[bp-20h]
mov [bp-1Ch],ax
mov ax,[bp-22h]
mov [bp-1Eh],ax
;xxxx:
;jmp xxxx
nexttile3:
inc word ptr [bp-20h]
cmp word ptr [bp-20h],3Ch
jl nextx2
inc word ptr [bp-22h]
cmp word ptr [bp-22h],28h
jl nexty2

mov word ptr     [bp-28h], 0
sendloop4:
mov     ax, [bp-28h]
cmp     ax, [bp-12h] ; Stack total units
jge     donesending3

mov     bx, si
mov     cl, 2
shl     bx, cl
les     bx, [bx-62B4h]
mov     ax, [bp-28h]
shl     ax, 1
add     bx, ax
mov     ax, es:[bx]
push ax

push    [bp-28h] ; Indexinstack
push    si    ; StackID
push    [bp-1Eh]    ; PosY
push    [bp-1Ch]    ; PosX
push    ax
push    cs
call    Assignmovement
add     sp, 0Ah

pop ax
call getoverland
; Store disembark position here! (bp-2A, bp-2C)
mov ax,[bp-2Ch]
sub ax,[bp-1Eh]
inc ax
sal ax,2
mov cx,[bp-2Ah]
sub cx,[bp-1Ch]
inc cx
add cx,ax
mov byte ptr es:[bx+1Dh],cl

inc word ptr     [bp-28h]
jmp sendloop4

donesending3:

nextstack2:

inc si
jmp nextstack


; in : bp-20h, bp-22h position
;===============================================================================
; tileacion : find if there is a tile we want to disembark to from our position
;===============================================================================
tileaction:
push di
mov word ptr [bp-0Ch],0FFFFh ; best unload position X
mov word ptr [bp-0Eh],0FFFFh ; best unload position Y
mov word ptr [bp-10h],0 ; best unload position priority
mov word ptr [bp-4],0 ; X modifier
nextx1:
mov word ptr [bp-6],0 ; Y modifier
nexty1:

call loadposition

; Position must be valid. Relevant land can't be on the edge of the map anyway.
cmp ax,28h
jge notland1
cmp ax,0
jl notland1
cmp cx,0
jl notland1
cmp cx,3Ch
jge notland1

call getcontinentID
or al,al   ; It's a sea tile...
jz notland1
mov [bp-8],al ; Continent ID

mov word ptr [bp-0Ah],0

call loadposition
call tileoccupied
or ax,ax ; Tile is empty
jz attackok
;jmp notland1 ;******** testing
; Tile has at least one unit on it!
call loadposition
call getstackstrength
mov [bp-0Ah],ax
test dx,08000h ; Not an enemy : can't attack
jz notland1
add ax,60
sal ax,1; We're leaving ships behind and miss chance to group with other unloaded troops so only do this if we are quite a lot stronger.
cmp word ptr [bp-1Ah],1 ; Don't attack with settler stacks
jz notland1
push ax
mov ax,[bp-22h]
mov cx,[bp-20h]
call getstackstrength
pop cx
cmp ax,cx
jle notland1 ; We are too weak to attack that
;=========================================================================
; Found a land tile we could move to, check if continent is appropriate
;=========================================================================
attackok:

cmp word ptr [bp-1Ah],1
jz settlerstack

;=========================================================================
; Not settler stack
;=========================================================================
; We don't care about continents type 5 and 6 (no targets)
call getcontinenttype
cmp al,5
jge notland1

; Is main action continent? If yes, top priority!
call get7050
cmp al,[bp-8]
jnz notmaincontinent1
call loadposition
mov dx,5000 ; Priority
add dx,[bp-0Ah] ; add strength of enemy : always prefer to attack when able
jmp foundpossiblelocation
notmaincontinent1:
; Can't have own or allied city on this continent unless it was the main action continent.
; this is to prevent getting off the ship where we got on.
xor di,di
nextcity:
call getcity
mov     al, es:[bx+11h]
cbw
cmp     ax, [bp+8] ; Plane
jnz nextcity2
mov al,es:[bx+10h]
mov cl,es:[bx+0Fh]
xor ah,ah
xor ch,ch
call getcontinentID
cmp al,[bp-8] ; Same continent?
jnz nextcity2
call getcity
mov     al, es:[bx+12h]
cbw
cmp     ax, [bp+6]
jz notland1 ; Own city on continent, we don't want to disembark here
push    ax
mov     ax, [bp+6]
mov     dx, 4C8h
imul    dx
pop     bx
add     bx, ax
cmp     byte ptr [bx-5FDEh], 2
jz notland1 ; Allied city!

nextcity2:
inc di
cmp di,[0BD94h]
jl nextcity

call loadposition
mov dx,10 ; Priority, less than on 7050 continent
add dx,[bp-0Ah] ; add strength of enemy : always prefer to attack when able
jmp foundpossiblelocation

;=========================================================================
; Settler stack
;=========================================================================
settlerstack:

call get7054

or ax,ax   ; If 7054 continent doesn't exist then anything goes
jz settlethis
cmp al,[bp-8]
jz settlethis
jmp notland1
settlethis:
call loadposition
mov dx,10 ; Priority doesn't really matter here, there is only one case...

foundpossiblelocation:
push ax
push bx
push cx
push dx
call cityexist
pop dx
or ax,ax
jz nocity2
add dx,600 ; 3 tiles of extra distance worth of priority for enemy cities.
; This much should be enough to hit them with nearby transports, while
; low enough to not make it impossible to manipulate the transport by
; moving garrisons in and out effectively.
nocity2:
pop cx
pop bx
pop ax



cmp [bp-10h],dx
jge notland1
mov [bp-10h],dx
mov [bp-0Ch],cx
mov [bp-0Eh],ax
notland1:

inc word ptr [bp-6]
cmp word ptr [bp-6],2
jle nexty1
inc word ptr [bp-4]
cmp word ptr [bp-4],2
jle nextx1
; return selected tile if any in bp-0C, bp-0E
pop di
retn

tileoccupied:
; Return 1 if tile has a unit
mov dl,cl   ; X
mov dh,al   ; Y
xor cx,cx
nextxx:
cmp cx,[0BD92h]
jge allchecked1
mov ax,cx
push dx
call getoverland
pop dx
cmp dx,es:[bx]
jnz notthere
mov al,es:[bx+2]
cmp al,[bp+8]
jnz notthere
haslair:
mov ax,1
retn
notthere:
inc cx
jmp nextxx

allchecked1:
call loadposition
call getstackstrength
or ax,ax
jnz haslair
retn

cityexist:
xor di,di
nextcity4:
call getcity
mov     al, es:[bx+11h]
cbw
cmp     ax, [bp+8] ; Plane
jnz nextcity5
call loadposition
cmp al,es:[bx+10h]
jnz nextcity5
cmp cl,es:[bx+0Fh]
jnz nextcity5
mov bl,es:[bx+12h]
xor bh,bh
sal bx,1
mov ax,4C8h
imul word ptr [bp+6] ; Wizard
add bx,ax
cmp word ptr [bx-5C98h],2 ; Must be hostile towards that wizard
jl nextcity5
mov ax,1
retn

nextcity5:
inc di
cmp di,[0BD94h]
jl nextcity4
xor ax,ax
retn


.org 0B92h
ShipAttackTarget:

.org 2DA6h
GetStacks:

.org 4FCBh
Assignmovement:

.org 516Dh
RemoveFromStack:
Reply

Monsters are still disappearing somewhere after "rampaging through a city and then disappearing into the wilderness." Here is early game save game where monster attacks the next turn if needed for debugging.


Attached Files
.zip   monster.zip (Size: 14.44 KB / Downloads: 0)
Reply

That works as intended now - they have to otherwise they'd stay in your city and cause problems. If the monsters win, they aren't sent back to the tile they came from.
Reply

After reading through the entire ship code I found no bugs that can be related. However it is definitely there - if I change the code to pretend none of the AI's stacks have any ships in them so nothing is actually done, the crash disappears. I'll have to keep looking...
Reply

Found the problem. When the stack contained a unit that was already removed from the stack and marked "absent" the game crashed because it still tried to set the new disembark tactic on it.

Fixed ship.zip was uploaded.
Reply

Thanks. I'm not sure if this is a bug but in that save2.zip save file there is by the way also a monster stack stuck one square above the town of "Fell Gorge", besides a tower, with nowhere to go except the sea or that red city where it doesn't go. However, couple of turns later red took care of the problem by attacking that stack.
Reply

Those are blocked from movement. While neutrals are allowed to move through and attack stacks of units on their way to a destination, cities, lairs, towers, nodes still count as impassable tiles. However, neutrals do not check for their target to be reachable when picking one - they assume any destination on the same continent should be reachable (or any destination is ok if the stack is capable of moving on water).
Overall, this is rare enough to not worth trying to fix - and even then it's very possible to have the tile be sealed by 2 lairs instead of a lair and a city.
Reply

How about letting neutrals move over lairs?
Reply

Having two different "targets" on the same tile is a bad idea, if someone moves on the tile they'd attack which one? Which one gets displayed? How does the AI target the tile? How do we prevent the stack from attacking the lair? Even if we manage to come up with a solution, it's too much work to implement from something like this.
Reply



Forum Jump: