Files
2025-05-04 16:58:12 +03:00

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