Nim game: Difference between revisions
Content added Content deleted
(Added XPL0 example.) |
(Added Z80 Assembly version) |
||
Line 4,398: | Line 4,398: | ||
Computer wins! |
Computer wins! |
||
</pre> |
|||
=={{header|Z80 Assembly}}== |
|||
{{works with|CP/M 3.1|YAZE-AG-2.51.2 Z80 emulator}} |
|||
{{works with|ZSM4 macro assembler|YAZE-AG-2.51.2 Z80 emulator}} |
|||
Use the /S8 switch on the ZSM4 assembler for 8 significant characters for labels and names<br><br> |
|||
This assembles to 99 bytes of instructions plus 98 bytes of static data for the texts and buffer, accounting for a total of 197 bytes. Not sure whether the 8080 and 8086 versions counted only instruction size or total program size, but the Z80 provides some powerful looping instructions that help to reduce program size.<br><br> |
|||
Please note that I did not bother with conversion from input characters to integers and using comparisons to validate them, nor did I use arithmetic to calculate the computer's move. Instead, I used fixed strings and the cpdr instruction to look up the user's input as well as the computer's response. The CP/M BDOS call ensures that the user can enter a single character only.<br> |
|||
<syntaxhighlight lang="z80"> |
|||
; |
|||
; Nim game using Z80 assembly language |
|||
; |
|||
; Runs under CP/M 3.1 on YAZE-AG-2.51.2 Z80 emulator |
|||
; Assembled with zsm4 on same emulator/OS, uses macro capabilities of said assembler |
|||
; Created with vim under Windows |
|||
; |
|||
; 2023-04-28 Xorph |
|||
; |
|||
; |
|||
; Useful definitions |
|||
; |
|||
bdos equ 05h ; Call to CP/M BDOS function |
|||
readstr equ 0ah ; Read string from console |
|||
wrtstr equ 09h ; Write string to console |
|||
cr equ 0dh ; ASCII control characters |
|||
lf equ 0ah |
|||
buflen equ 01h ; Length of input buffer |
|||
maxtok equ 12 ; Starting number of tokens |
|||
; |
|||
; Macro for BDOS calls |
|||
; |
|||
readln macro buf ; Read a line from input |
|||
push bc |
|||
ld c,readstr |
|||
ld de,buf |
|||
call bdos |
|||
pop bc |
|||
endm |
|||
; |
|||
; ===================== |
|||
; Start of main program |
|||
; ===================== |
|||
; |
|||
cseg |
|||
ld de,nim ; Print title and initialize |
|||
call print |
|||
ld c,maxtok ; Register c keeps track of remaining tokens |
|||
loop: |
|||
ld de,tokens ; Print the remaining tokens |
|||
call print |
|||
ld b,c ; Use b for loop to print remaining tokens |
|||
printtk: |
|||
ld de,token |
|||
call print |
|||
djnz printtk |
|||
ld de,prompt ; Prompt user for input |
|||
call print |
|||
readln inputbuf |
|||
ld a,(bufcont) ; Now check input for validity and compute response |
|||
ld hl,validinp+2 ; Start from end of valid string, so bc gets set to numeric equivalent |
|||
push bc ; Save token counter, use bc for cpdr |
|||
ld bc,3 |
|||
cpdr ; Use automatic search function |
|||
jr nz,printerr ; If input character not found, print error |
|||
ld hl,mymoves ; Get character for response into a |
|||
add hl,bc ; bc contains index into check string as well as response string |
|||
pop bc |
|||
ld a,(hl) |
|||
ld (outbuf),a ; Put it in output buffer |
|||
ld de,response ; Print the computer's move |
|||
call print |
|||
ld a,c ; Subtract 4 tokens from counter |
|||
sub 4 |
|||
ld c,a |
|||
jr nz,loop ; If not finished, repeat |
|||
ld de,lose ; Otherwise, player lost |
|||
call print |
|||
ret ; Return to CP/M |
|||
printerr: ; Print error message and try again |
|||
pop bc |
|||
ld de,wronginp |
|||
call print |
|||
jp loop |
|||
print: ; Use subroutine instead of macro for smaller code |
|||
push bc |
|||
ld c,wrtstr |
|||
call bdos |
|||
pop bc |
|||
ret |
|||
; |
|||
; =================== |
|||
; End of main program |
|||
; =================== |
|||
; |
|||
; |
|||
; ================ |
|||
; Data definitions |
|||
; ================ |
|||
; |
|||
dseg |
|||
inputbuf: ; Input buffer |
|||
defb buflen ; Maximum possible length |
|||
defb 00h ; Returned length of actual input |
|||
bufcont: |
|||
defs buflen ; Actual input area |
|||
nim: |
|||
defb 'Nim$' ; Dialog texts |
|||
prompt: |
|||
defb cr,lf,'How many will you take (1-3)? $' |
|||
response: |
|||
defb cr,lf,'I take ' ; No $ here! Saves one print command |
|||
outbuf: |
|||
defb ' $' ; For printing response |
|||
tokens: |
|||
defb cr,lf,cr,lf,'Tokens: $' |
|||
token: |
|||
defb '|$' |
|||
lose: |
|||
defb cr,lf,'You lose!$' |
|||
wronginp: |
|||
defb cr,lf,'Wrong input$' |
|||
validinp: |
|||
defb '123' ; Valid input |
|||
mymoves: |
|||
defb '321' ; Computer's response |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
E>nim |
|||
Nim |
|||
Tokens: |||||||||||| |
|||
How many will you take (1-3)? 2 |
|||
I take 2 |
|||
Tokens: |||||||| |
|||
How many will you take (1-3)? 4 |
|||
Wrong input |
|||
Tokens: |||||||| |
|||
How many will you take (1-3)? 3 |
|||
I take 1 |
|||
Tokens: |||| |
|||
How many will you take (1-3)? 1 |
|||
I take 3 |
|||
You lose! |
|||
E> |
|||
</pre> |
</pre> |