165 lines
6.9 KiB
Plaintext
165 lines
6.9 KiB
Plaintext
; A Blackjack port in N8A assembly for n808 VM
|
|
; How to play:
|
|
; * you start with a $1000 balance
|
|
; * on each round, enter your bet
|
|
; (the game will quit if the bet is above your balance)
|
|
; * if you hit a blackjack, your balance will increase immediately
|
|
; * if the dealer hits a blackjack, your balance will decrease immediately
|
|
; * the first card of the dealer's hand will be shown
|
|
; (card values are: ace is 101, 2 to 9 are "as is", 10 is 10 to K)
|
|
; * on the first turn, select 0 (stand), 1 (hit) or 2 (double)
|
|
; * on each next turn, select 0 (stand) or 1 (hit)
|
|
; * as a result of the round, the dealer's final hand will be shown
|
|
; first and then yours
|
|
; * the dealer must draw on 16 and stand on any 17
|
|
; * player's blackjack pays 3 to 2
|
|
; Created by Luxferre in 2025, released into public domain
|
|
|
|
; constant/variable space
|
|
#1 va
|
|
#2 vb
|
|
#3 vc
|
|
#4 vd
|
|
#5 action
|
|
#6 dscore
|
|
#7 pscore
|
|
#127 c1
|
|
#51 c5
|
|
#52 c_13
|
|
#53 c_hund
|
|
#54 c_ds
|
|
#60 balance
|
|
#61 bet
|
|
#62 dhand
|
|
#63 phand
|
|
#64 round
|
|
#65 stand
|
|
|
|
; constant assignments
|
|
dca 5 @c5
|
|
dca 13 @c_13
|
|
dca 36 @c_ds
|
|
dca 100 @c_hund
|
|
dca 0 @balance
|
|
set 10 0 @balance
|
|
|
|
juc :main ; jump to the main code after initialization
|
|
|
|
; card retrieval procedure
|
|
; the resulting card is in the @vc cell
|
|
:gcard rnd @c1 @c_13 @va ; get a random number from 1 to 13 incl
|
|
dca 10 @vb ; assign 10 to the second buffer
|
|
div @va @vb ; va / 10 => vb
|
|
dca 0 @vc ; 0 => vc
|
|
mdf @vb @vc ; floor(va/10) => vc
|
|
sub @c1 @vc ; subtract it from 1
|
|
mul @va @vc ; multiply it by the random choice itself
|
|
jgt @vc :gnext ; skip the next part if > 0
|
|
dca 10 @vc ; return 10
|
|
ret
|
|
:gnext dec @vc ; decrement
|
|
jne @vc :gnr ; skip the next part if == 0
|
|
add @c_hund @vc ; add 100
|
|
:gnr inc @vc ; increment back
|
|
ret
|
|
|
|
; scoring procedure, parameter is in the @va cell
|
|
; the result is in the @vc cell
|
|
:score dca 112 @vb ; set vb to 112
|
|
sub @va @vb ; set vb to va - 112
|
|
jge @vb :skscore ; skip adding 10 if >= 112
|
|
dca 100 @vb ; set vb to 100
|
|
sub @va @vb ; set vb to va - 100
|
|
jlt @vb :skscore ; skip adding 10 if < 100
|
|
dca 10 @vb ; set vb to 10
|
|
add @vb @va ; add 10 to va value
|
|
:skscore dca 100 @vc ; set 100 to vc
|
|
mdf @va @vc ; set vc to va mod 100
|
|
ret
|
|
|
|
; main code part
|
|
|
|
:main ouc @c_ds @c_ds ; output a dollar sign if supported
|
|
out @balance @balance ; output the current balance
|
|
jle @balance :end ; game over if zero or less
|
|
inp @bet @bet ; input your bet
|
|
dva @bet @va ; buffer the bet
|
|
sub @balance @va ; va = balance - bet
|
|
jlt @va :end ; game over if the bet is invalid
|
|
dva @va @balance ; restore the balance value from va
|
|
jpr :gcard ; call the card generation procedure
|
|
dva @vc @dhand ; copy the result as the dealer's hand value
|
|
dva @vc @vd ; copy the first dealer hand card into vd
|
|
jpr :gcard ; call the card generation procedure again
|
|
add @vc @dhand ; complete the dealer's hand
|
|
dva @dhand @va ; copy the dealer's hand as the va param
|
|
jpr :score ; run the scoring procedure (result in @vc)
|
|
dca 21 @va ; set the constant 21 to @va
|
|
sub @vc @va ; compare the procedure result with 21
|
|
jeq @va :main ; loop back if we have the dealer's blackjack
|
|
jpr :gcard ; call the card generation procedure
|
|
dva @vc @phand ; save the first card into the player's hand
|
|
jpr :gcard ; call the card generation procedure
|
|
add @vc @phand ; add the second card into the player's hand
|
|
dca 111 @va ; prepare constant 111
|
|
sub @phand @va ; compare player's hand to 111
|
|
jeq @va :bjk ; jump to blackjack condition on player's blackjack
|
|
out @vd @vd ; display the start of the dealer's hand
|
|
dca 0 @round ; set the round index to 0
|
|
dca 0 @stand ; set the stand flag to 0
|
|
:rnl out @phand @phand ; start of the inner player loop, display the player's hand
|
|
inp @action @action ; input the action value
|
|
jeq @action :std ; jump to stand action if 0
|
|
dec @action ; check if 1
|
|
jeq @action :hit ; jump to hit action if 1
|
|
dec @action ; check if 2
|
|
jeq @action :dbl ; jump to double action if 2
|
|
juc :skp ; skip otherwise
|
|
:dbl jne @round :skp ; skip double if not the first round
|
|
dva @bet @va ; buffer the bet
|
|
sub @balance @va ; subtract more balance
|
|
dva @va @balance ; restore the variable
|
|
add @bet @bet ; double the bet
|
|
dca 1 @stand ; set the stand flag, proceed to the hit section
|
|
:hit jpr :gcard ; generate a new card in @vc
|
|
add @vc @phand ; add it to the player's hand
|
|
inc @round ; increment the round index
|
|
juc :skp ; jump to skip the rest
|
|
:std dca 1 @stand ; just set the stand flag
|
|
inc @round ; increment the round index
|
|
:skp dva @phand @va ; set the player's hand as a parameter to @va
|
|
jpr :score ; call the scoring procedure (result in @vc)
|
|
dca 21 @va ; set 21 to va
|
|
sub @vc @va ; subtract 21 from the result
|
|
jle @va :nob ; reloop to beginning if the player is bust
|
|
out @phand @phand ; output the player's hand
|
|
juc :main ; reloop
|
|
:nob jeq @stand :rnl ; repeat the inner loop if the stand flag is 0
|
|
dva @vc @pscore ; at this point, player score is now in @vc
|
|
:rdl dva @dhand @va ; start the inner dealer loop, set the dealer hand param
|
|
jpr :score ; call the scoring procedure (result in @vc)
|
|
dva @vc @dscore ; save the dealer's score
|
|
dca 16 @va ; compare @vc with 16
|
|
sub @vc @va ; the difference is in @va
|
|
jgt @va :dbrk ; go to stand if the difference is over 16
|
|
jpr :gcard ; call the card generation procedure
|
|
add @vc @dhand ; add the result to dealer's hand
|
|
juc :rdl ; repeat the inner dealer loop
|
|
:dbrk out @dhand @phand ; output both hands (dealer's first)
|
|
dva @pscore @va ; buffer the player's score
|
|
sub @dscore @va ; subtract it from the dealer's score
|
|
jeq @va :push ; push condition
|
|
jlt @va :win ; player win condition
|
|
dca 21 @va ; prepare constant 21
|
|
sub @dscore @va ; compare dealer's score with 21
|
|
jgt @va :win ; player win condition
|
|
juc :main ; reloop to beginning
|
|
:bjk dca 2 @va ; set 2 to @va
|
|
div @bet @va ; halve the bet
|
|
add @va @balance ; add half the bet to the balance
|
|
:win add @bet @balance ; add the bet the first time
|
|
:push add @bet @balance ; add the bet the second time
|
|
juc :main ; reloop to beginning
|
|
:end nnn ; program end label
|
|
|