; 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