Files
scorch_src/ai.asm
T
2022-07-03 13:22:44 -04:00

430 lines
8.3 KiB
NASM

; @com.wudsn.ide.asm.mainsourcefile=scorch.asm
; artificial intelligence of tanks goes here!
; in A there is a level of tank's intelligence
; 1-moron, ..., 7-cyborg, 8-UNKNOWN (the best of all)
; at the moment (2003-08-15) I have no idea how
; to program better opponents, but moron is easy -
; - shoots random direction and force
; greeeting to myself 10 years older in 2013-11-09... still no idea
;----------------------------------------------
.proc MakeLowResDistances
; create low precision table of positions
; by dividing positions by 4
ldy #MaxPlayers-1
loop
lda xtankstableL,y
sta temp
lda xtankstableH,y
sta temp+1
;= /4
:2 lsrw temp
lda temp
sta LowResDistances,y
dey
bpl loop
rts
.endp
;----------------------------------------------
.proc ArtificialIntelligence ;
; A - skill of the TankNr
; returns shoot energy and angle in
; ForceTable/L/H and AngleTable
;----------------------------------------------
asl
tax
:2 dex ;credit KK
lda AIRoutines+1,x
pha
lda AIRoutines,x
pha
ldx TankNr ; common values used in AI routines
; address of weapons table (for future use)
lda TanksWeaponsTableL,x
sta temp
lda TanksWeaponsTableH,x
sta temp+1
rts
.endp
;----------------
AIRoutines
.word Moron-1
.word Shooter-1 ;Shooter
.word Poolshark-1 ;Poolshark
.word Toosser-1 ;Toosser
.word Poolshark-1 ;Chooser
.word Poolshark-1 ;Spoiler
.word Poolshark-1 ;Cyborg
.word Poolshark-1 ;Unknown
;----------------------------------------------
.proc Moron
jsr RandomizeAngle
sta NewAngle
mwa #80 RandBoundaryLow
mwa #800 RandBoundaryHigh
jsr RandomizeForce
rts
.endp
;----------------------------------------------
.proc Shooter
lda PreviousAngle,x
ora PreviousEnergyL,x
ora PreviousEnergyH,x
beq firstShoot
lda PreviousAngle,x
clc
adc #5
cmp #180
bcc @+
lda #0
@
sta NewAngle
sec
lda PreviousEnergyL,x
sbc #5
sta ForceTableL,x
lda PreviousEnergyH,x
sbc #0
sta ForceTableH,x
jmp endo
firstShoot
; compare the x position with the middle of the screen
lda xTanksTableH,x
cmp #>(screenwidth/2)
bne @+
lda xTanksTableL,x
cmp #<(screenwidth/2)
@ bcc tankIsOnTheRight
; enemy tank is on the left
randomize 95 125
sta NewAngle
bne forceNow
tankIsOnTheRight
randomize 55 85
sta NewAngle
forceNow
mwa #100 RandBoundaryLow
mwa #800 RandBoundaryHigh
;ldx TankNr ;this is possibly not necessary
jsr RandomizeForce
endo
;ldx TankNr ;this is possibly not necessary
jsr RandomizeForce.LimitForce
lda NewAngle
sta PreviousAngle,x
lda ForceTableL,x
sta PreviousEnergyL,x
lda ForceTableH,x
sta PreviousEnergyH,x
; choose the best weapon
ldy #32 ;the last weapon
loop
dey
lda (temp),y ; this is set up before calling the routine, has address of TanksWeaponsTable
beq loop
tya
sta ActiveWeapon,x
rts
.endp
;----------------------------------------------
.proc Poolshark
; defensives
; if low energy ten use battery
lda Energy,x
cmp #30
bcs EnoughEnergy
; lower than 30 units - check battery
ldy #ind_Battery________
lda (temp),y ; has address of TanksWeaponsTable
beq NoBatteries
; we have batteries - use one
clc
sbc #1
sta (temp),y
lda #99
sta Energy,x
NoBatteries
EnoughEnergy
; use best defensive :)
; but not allways
randomize 1 3
cmp #1
bne NoUseDefensive
; first check check if any is in use
lda ActiveDefenceWeapon,x
bne DefensiveInUse
ldy #ind_Nuclear_Winter_+1 ;the last defensive weapon
@
dey
cpy #ind_Battery________ ;first defensive weapon (White Flag nad Battery - never use)
beq NoUseDefensive
lda (temp),y ; has address of TanksWeaponsTable
beq @-
tya
; activate defensive weapon
sta ActiveDefenceWeapon,x
lda DefensiveEnergy,y
sta ShieldEnergy,x
; decrease in inventory
clc
sbc #1
sta (temp),y ; has address of TanksWeaponsTable
NoUseDefensive
DefensiveInUse
firstShoot
;find nearest tank neighbour
jsr MakeLowResDistances
mva #$ff temp2 ; min possible distance
;ldx TankNr
ldy NumberOfPlayers
dey
loop01
cpy TankNr
beq skipThisPlayer
lda eXistenZ,y
beq skipThisPlayer
lda LowResDistances,x
cmp LowResDistances,y
bcs EnemyOnTheLeft
;enemy on the right
sec
lda LowResDistances,y
sbc LowResDistances,x
cmp temp2 ; lowest
bcs lowestIsLower
sta temp2
sty temp2+1 ; number of the closest tank
; calculate index to shotangle table
:3 lsr @
and #%00000111
clc
adc #8
sta AngleTablePointer
jmp lowestIsLower
EnemyOnTheLeft
sec
lda LowResDistances,x
sbc LowResDistances,y
cmp temp2 ; lowest
bcs lowestIsLower
sta temp2
sty temp2+1 ; number of the closest tank
; calculate index to shotangle table
:3 lsr @
and #%00000111
eor #%00000111
sta AngleTablePointer
lowestIsLower
skipThisPlayer
dey
bpl loop01
randomize 0 8
ldy AngleTablePointer
clc
adc AngleTable,y
sta NewAngle
forceNow
mwa #300 RandBoundaryLow
mwa #700 RandBoundaryHigh
ldx TankNr
jsr RandomizeForce
endo
;ldx TankNr ;this is possibly not necessary
; choose the best weapon
lda TanksWeaponsTableL,x
sta temp
lda TanksWeaponsTableH,x
sta temp+1
ldy #32 ;the last weapon
loop
dey
lda (temp),y
beq loop
tya
sta ActiveWeapon,x
rts
;----------------------------------------------
AngleTable ; 16 bytes ;ba w $348b L$3350
.by 106,114,122,130,138,146,154,162
.by 18,26,34,43,50,58,66,74
.endp
;----------------------------------------------
.proc Toosser
; use best defensive :)
; allways
; first check check if any is in use
lda ActiveDefenceWeapon,x
bne DefensiveInUse
ldy #64 ;the last defensive weapon
@
dey
cpy #ind_Battery________ ;first defensive weapon (White Flag nad Battery - never use)
beq NoUseDefensive
lda (temp),y ; has address of TanksWeaponsTable
beq @-
tya
; activate defensive weapon
sta ActiveDefenceWeapon,x
lda DefensiveEnergy,y
sta ShieldEnergy,x
; decrease in inventory
clc
sbc #1
sta (temp),y
DefensiveInUse
NoUseDefensive
; Toosser is like Poolshark but allways uses defensives
jmp Poolshark
.endp
;----------------------------------------------
.proc PurchaseAI ;
; A - skill of the TankNr
; makes purchase for AI opponents
; results of this routine are not visible on the screen
;----------------------------------------------
asl
tax
:2 dex ;credit KK
lda PurchaseAIRoutines+1,x
pha
lda PurchaseAIRoutines,x
pha
rts
.endp
;----------------
PurchaseAIRoutines
.word MoronPurchase-1
.word ShooterPurchase-1 ;ShooterPurchase
.word PoolsharkPurchase-1 ;PoolsharkPurchase
.word PoolsharkPurchase-1 ;ToosserPurchase
.word PoolsharkPurchase-1 ;ChooserPurchase
.word PoolsharkPurchase-1 ;SpoilerPurchase
.word PoolsharkPurchase-1 ;CyborgPurchase
.word PoolsharkPurchase-1 ;UnknownPurchase
;----------------------------------------------
.proc MoronPurchase
;Moron buys nothing
rts
.endp
;-------
.proc TryToPurchaseOnePiece
; A - weapon number, better it will be in range(1,32)
; TankNr in X
tay
lda PurchaseMeTable,y
beq SorryNoPurchase
lda WeaponPriceL,y
sta temp
lda WeaponPriceH,y
sta temp+1
;price of the weapon in temp
lda MoneyL,x
sta temp2
lda MoneyH,x
sta temp2+1
;current monies in temp2
cpw temp2 temp
bcc SorryNoPurchase
; deduct monies from the bank account
sec
lda temp2
sbc temp
sta MoneyL,x
lda temp2+1
sbc temp+1
sta MoneyH,x
lda TanksWeaponsTableL,x
sta temp
lda TanksWeaponsTableH,x
sta temp+1
lda WeaponUnits,y
clc
adc (temp),y
cmp #99 ;max number of weapon units
bcc NotExceeded
lda #99
NotExceeded
sta (temp),y
SorryNoPurchase
rts
.endp
;----------------------------------------------
.proc ShooterPurchase
; first try to buy defensives
mva #2 tempXroller; number of offensive purchases to perform
ldx TankNr
@
randomize 49 55
jsr TryToPurchaseOnePiece
dec tempXroller
bne @-
; and now offensives
mva #4 tempXroller; number of offensive purchases to perform
ldx TankNr
@
randomize 1 14
jsr TryToPurchaseOnePiece
dec tempXroller
bne @-
rts
.endp
;----------------------------------------------
.proc PoolsharkPurchase
; first try to buy defensives
mva #3 tempXroller; number of offensive purchases to perform
ldx TankNr
@
randomize 49 61
jsr TryToPurchaseOnePiece
dec tempXroller
bne @-
; and now offensives
mva #8 tempXroller; number of purchases to perform
ldx TankNr
@
randomize 1 30
jsr TryToPurchaseOnePiece
dec tempXroller
bne @-
rts
.endp