Tutorial 15
Nous allons faire un jeu !

Survol
    Nous allons faire un jeu de morpion ! Ce jeu n'utilisera pas de sprite, à moins que vous ne considériez qu'un curseur se déplaçant sur un tableau ne soit un sprite :) Je remercie spécialement Robert Senser pour m'avoir fourni ce programme!

Préparation
    Tout d'abord je vais expliquer les ROM calls _grfufclr et _grbufcpy.   _Grfufclr vide le buffer vidéo et tous les 768 octets de plotsscreen sont remis à zéro. Le _grbufcpy affichera ce qui est stocké dans le buffer plotsscreen.

Programmation
    Le programme ci-dessous est long, mais n'est pas plus difficile que tout ce que nous avons vu jusqu'à maintenant. Attention... Prêt... Programmez!

 empty    .equ       0
 oh         .equ       1
 ohwin     .equ       3           ;oh * 3!
 ex         .equ       4
 exwin     .equ       12         ;ex * 3!
 false      .equ       0
 true       .equ       1

 keyquit .equ       $40
 keyins   .equ       $0B
 keyup    .equ       $03
 keydn    .equ       $04
 keyrght .equ       $01
 keyleft   .equ       $02
 keyentr .equ       $05

 #define B_CALL(xxxx)   rst 28h \ .dw xxxx           ;  Nous allons seulement utiliser   B_CALL

 _RunIndicOff                  =4570h
 _grbufclr                       = 4BD0h
 _grbufcpy                      = 486Ah
 plotsscreen                    = 9340h

 _getkey                         = 4972h
 _puts                            = 450Ah
 _putc                            = 4504h
 _newline                        = 452Eh
 _clrlcdfull                       = 4540h
 _clrscrf                          = 4546h
 _homeup                       = 4558h

 appTextSave     .equ       1
 appFlags           .equ       13
 textInverse         .equ       3
 textflags                        .equ       5


              .org       $9D95

B_CALL(_RunIndicOff) ; Désactive l'indicateur d'exécution
              B_CALL(_grbufclr)                      ;  vide le buffer
              ld          hl,picture                       ;  prend l'adresse  get address of splash screeen
              ld          de,plotsscreen               ;  prend l'adresse du buffer graphique de la TI
              ld          bc,768                          ;  Définit le nombre d'octets à copier   (96*64)/8
              ldir                                            ;  copie les octets
              B_CALL(_grbufcpy)                    ;  lie l'image graphique

 ; set the flip-flip flag
              ld          a,false
              ld          (flag),a
              ld          (skip),a
                                                 ; start of game
 newgme             B_CALL(_getkey)                       ; wait for a key to be pressed
              cp         keyquit
              jp          z,bye                 ; exit
 newgme2 ld       a,empty                                  ; clear the playing grid
              ld          (grid0),a
              ld          hl,grid0
              ld          de,grid0
              ld          bc,8
              ldir
              ld          a,true                ; preset the cursor grid
              ld          (cur0),a
              ld          a,false
              ld          (cur0+1),a
              ld          hl,cur0+1
              ld          de,cur0+2
              ld          bc,8
              ldir
                                                 ; pick symbol for person and ti
              ld          a,(flag)
              cp         true
              jr           z,new1

 ld          a,true
              ld          (flag),a
              ld          a,ex
              ld          (person),a
              ld          a,oh
              ld          (tisymb),a
              ld          a,false
              ld          (skip),a
              ld          hl,youex
              jr           main2
 new1                 ld          a,false
              ld          (flag),a
              ld          a,oh
              ld          (person),a
              ld          a,ex
              ld          (tisymb),a
              ld          a,true
              ld          (skip),a
              ld          hl,youoh
              jr           main2
                                                 ; main processing loop   
 main      ld          hl,nomsg
 main2                call show                                 ; show the current grid
              ld          a,(skip)
              cp         true
              jp          z,aihere             ; let the ti go first
              B_CALL(_getkey)                                  ; get the next key input
              cp         keyquit
              jp          z,bye                 ; exit
              cp         keyins
              jp          z,newgme2

 cp         keyup
              jr           nz,trydn             ; up pushed
              call        up3
              jp          main     
 trydn      cp         keydn
              jr           nz,tryrght           ; down pushed
              call        dn3
              jp          main
 tryrght    cp         keyrght
              jr           nz,tryleft            ; right pushed
              call        rght3
              jp          main
 tryleft     cp         keyleft  
              jr           nz,tryentr           ; left pushed
              call        left3
              jp          main
 tryentr cp           keyentr
              ld          hl,badmsg
              jp          nz,main2           ; enter pushed, other keys ignored
                                                ; find the current cursor location
              ld          hl,cur0
              ld          b,9
 fdloop    ld          a,(hl)
              cp         true
 jr           nz,fdnext
                                                 ; found cursor location!
              ld          bc,-9
              add        hl,bc                  ; back into the grid
                                                 ; see if empty
              ld          a,(hl)
              cp         empty
              jr           nz,fderr
                                                 ; if so, insert symbol
              ld          a,(person)
              ld          (hl),a     
              call        chkwin
              cp         true
              jp          z,newgme
              jr           aihere
 fderr       ld          hl,badloc
              jp          main2
                                                 ; CAUTION -- AI at work here!!!
 aihere    ld          a,false
              ld          (skip),a
              call        timove
              call        chkwin
              cp         true
              jp          z,newgme
              ld          a,(flag)
              cp         true
              jr           z,fdmsg
              ld          hl,youoh                        ;show oh msg
jp          main2   
 fdmsg                ld          hl,youex                        ;show ex msg
              jp          main2
 fdnext    inc         hl
              djnz       fdloop
              jp          z,main               ; something is wrong...
                                                 ; ignore error
              jp          main
                                                 ; main exit point
 bye
              call        clrhme               ; clear screen
              ld          hl,byemsg
              B_CALL(_puts)
              B_CALL(_newline)
              ret                                 ; return to being a mere calculator
 ;
 clrhme   set        appTextSave,(iy+appFlags) ; get text shadow too
              B_CALL(_clrlcdfull)                     ; clear lcd
              B_CALL(_clrscrfull)                    ; clear scr
              B_CALL(_homeup)                     ; home the cursor
              ret
 ;TI GAME STRATEGY
 ; ti makes a move
 ; strategy:
 ; 1) Can ti win, if so then do it
 ; 2) Can "wet-ware" win, if so then take it the square first
 ; 3) Can ti take the center, if so then take it
 ; 4) Can ti take a corner, if so then take it
 ; 5) else, take an open spot
 timove    ld          b,9
              ld          hl,grid0
 tiloop1               ld          a,(hl)
              cp         empty
              jr           nz,tinext1
              push      hl
              push      bc
              ld          a,(tisymb)
              ld          (hl),a
              call        chkwin
              pop        bc
              pop        hl
              cp         true
              jr           z,tifnd                ; winning move!  
              ld          a,empty
              ld          (hl),a                 ; remove trial move
 tinext1 inc          hl
              djnz       tiloop1
                                                 ;check for defensive move
              ld          b,9
              ld          hl,grid0
 tiloop2               ld          a,(hl)
              cp         empty
              jr           nz,tinext2
              push      hl
              push      bc
              ld          a,(person)
              ld          (hl),a
              call        chkwin
              pop        bc
              pop        hl
              ld          d,a
              ld          a,empty
              ld          (hl),a
              ld          a,d
              cp         true
              jr           z,tifnd                ; good defensive move!
 tinext2   inc         hl
              djnz       tiloop2
                                                 ;check the center
              ld          hl,grid0+4
              ld          a,(hl)
              cp         empty
              jr           z,tifnd
                                                 ;check the corners (and center again)
              ld          b,5
              ld          hl,grid0
 tiloop4   ld          a,(hl)
              cp         empty
              jr           z,tifnd
              inc         hl                      ; +2 goes corner to corner ...

 inc         hl
              djnz       tiloop4
                                                 ;try anyplace (could optimize, but....)
              ld          b,9
              ld          hl,grid0
 tiloop5   ld          a,(hl)
              cp         empty
              jr           z,tifnd
              inc         hl
              djnz       tiloop5
              jr           tiexit
 tifnd       ld          a,(tisymb)
              ld          (hl),a
 tiexit      ret
                                                            ; check for a winner, return true in a if so, else false
 chkwin               ld          hl,chktab
              push      hl
              pop        ix                                  ;table addr -> ix
                                                             ;start outer loop
 chkloop ld          a,(hl)                 ;are we done?
              cp         0
              jr           z,chknaw                       ;yes, then no winner!
              inc         hl                      ;get to address
              ld          e,(hl)                 ;woaw!!!   (hl) -> hl
              inc         hl                      ; woaw!!!
              ld          d,(hl)                 ;   woaw!!!
              push      de                     ;   woaw!!
              pop        hl                      ; de -> hl
              ld          d,0
              ld          e,a                    ;de is increment value
              ld          b,3                    ;b is loop count
              ld          a,0                    ;a is sum           add        hl,de
                                                 ;start inner loop
 chk1     add        a,(hl)
              add        hl,de
              djnz       chk1
              cp         ohwin
              jr           nz,chk1n
              ld          hl,ohwins           ; O wins!
              jr           chkwinr
 chk1n    cp         exwin
              jr           nz,chkno
              ld          hl,exwins           ; X wins
              jr           chkwinr
 ;end inner         
 chkno    push      ix         
              pop        hl                      ; ix -> hl
              inc         hl                      ; add 3
              inc         hl
              inc         hl
              push      hl
              pop        ix                      ; hl -> ix
              jr           chkloop ;no win this line
                                                 ;end outer
                                                 ; exit outer loop early, crow about success and mark win
 chkwinr call        show
              ld          a,true
              jr           chkbye
 chknaw ld          hl,grid0              ;See about the cat
              ld          b,9
 chklop   ld          a,(hl)
              cp         empty
              jr           z,chkncat
              inc         hl
              djnz       chklop
              ld          hl,catmsg                      ;Darn cat!
              call        show
              ld          a,true
              jr           chkbye
 chkncat             ld          a,false
 chkbye ret
                                                 ; this routine works by summing values in grid, 8 possible cases
 chktab   .db        1                       ;covers the 8 cases!
              .dw        grid0
              .db        1
              .dw        grid1
              .db        1
              .dw        grid2
              .db        3
              .dw        grid0
              .db        3
              .dw        grid0+1
              .db        3
              .dw        grid0+2
              .db        4
              .dw        grid0
              .db        2
              .dw        grid0+2
              .db        0                       ;end of table marker

                                                 ; move "cursor" up
 up3        ld          hl,cur0
              ld          de,curx
              call        mov3
              ld          hl,cur1
              ld          de,cur0
              call        mov3
              ld          hl,cur2
              ld          de,cur1
              call        mov3
              ld          hl,curx
              ld          de,cur2
              call        mov3
              ret
                                                 ; move "cursor" down
 dn3        ld          hl,cur0
               ld          de,curx
              call        mov3

 ld          hl,cur2
              ld          de,cur0
              call        mov3
              ld          hl,cur1
              ld          de,cur2
              call        mov3
              ld          hl,curx
              ld          de,cur1
              call        mov3
              ret
                                                 ; helper routine
 mov3     ld          bc,3
              ldir
              ret
                                                 ; move "cursor" right
 rght3      ld          hl,cur0
              call        shtr3
              ld          hl,cur1
              call        shtr3
              ld          hl,cur2
              call        shtr3
              ret
                                                 ; helper routine
 shtr3     push      hl
              ld          a,(hl)
              inc         hl
              ld          b,(hl)
              inc         hl
              ld          c,(hl)
              pop        hl
              ld          (hl),c
              inc         hl
              ld          (hl),a
              inc         hl
              ld          (hl),b
              ret
                                                 ; move "cursor" left
 left3       ld          hl,cur0
              call        shtl3
              ld          hl,cur1
              call        shtl3

 ld          hl,cur2
              call        shtl3
              ret
                                                 ; helper routine

 shtl3      push      hl
              ld          a,(hl)
              inc         hl
              ld          b,(hl)
              inc         hl
              ld          c,(hl)
              pop        hl
              ld          (hl),b
              inc         hl
              ld          (hl),c
              inc         hl
              ld          (hl),a
              ret
                                                 ; show the tic-tac-toe grid on the screen
 show     push      hl                      ; keep possible message           
              call        clrhme               ; clear/home screen
              ld          hl,grid0              ; process row 0
              call        showrow
              ld          hl,dashs
              B_CALL(_puts)
              B_CALL(_newline)
              ld          hl,grid1              ; process row 1
              call        showrow
              ld          hl,dashs
              B_CALL(_puts)
              B_CALL(_newline)
              ld          hl,grid2              ; process row 2
              call        showrow
              pop        hl                      ; process message if there
              ld          a,(hl)
              cp         0
              jr           z,showby
              push      hl
              B_CALL(_newline)
              B_CALL(_newline)
              pop        hl
              B_CALL(_puts)

 showby ret

 showrow
              push      hl
              call        showspot           ; show first spot
              ld          a,(bar)
              B_CALL(_putc)
              pop        hl
              inc         hl
              push      hl
              call        showspot           ; show 2nd spot
              ld          a,(bar)
              B_CALL(_putc)
              pop        hl
              inc         hl
              call        showspot           ; show 3rd spot
              B_CALL(_newline)
              ret

                                                 ; show the symbol at (hl), and handle cursor
 showspot
              push      hl                      ; need this later
              ld          bc,9
              add        hl,bc
              ld          a,(hl)                 ; load cursor flag
              pop        hl
              cp         false
              res        textInverse,(iy+textflags)
              jr           z,shownch
              set        textInverse,(iy+textflags)
 shownch                                               ; load actual item in spot
              ld          a,(hl)
              cp         empty
              jr           nz,shownot1
              ld          a,(space)
              jr           showgun
 shownot1
              cp         oh
              jr           nz,shownot2
              ld          a,(leto)
              jr           showgun
 shownot2
              ld          a,(letx)
 showgun            bcall(_putc)
              res        textInverse,(iy+textflags)
              ret
                                                 ; these are really variables
 grid        .equ       *
 grid0      .db        empty,empty,empty
 grid1      .db        empty,empty,empty
 grid2      .db        empty,empty,empty
                                                 ; this must be 9 bytes past grid0 or else it will fail
 cur0       .db        true,false,false
 cur1       .db        false,false,false
 cur2       .db        false,false,false
 curx       .db        0,0,0
 person   .db        0

 tisymb   .db        0
 flag        .db        0
 skip       .db        0
                                                 ; basically, these are constants
 nine       .db        9
 space    .db        " "
 leto        .db        "O"
 letx        .db        "X"
 bar        .db        "|"
 dashs    .db        "-----",0
 ; youmsg           .db        "Your move!",0

 

 youex    .db        "Your move 'X'!",0
 youoh    .db        "Your move 'O'!",0
 ohwins   .db        "** O ** Wins!",0
 exwins   .db        "** X ** Wins!",0
 catmsg .db        "* Cat got it *",0
 nomsg   .db        0
 badmsg             .db        "Invalid key!",0
 badloc   .db        "Place taken!",0
 byemsg             .db        "Game over.",0

 picture:
              #include "title.asm"     ; graphic image from file poets.asm

 .end
 END


    This is the title.asm screen that will be displayed at the start of the program, start a new text file and copy this into it. Don't try to copy it by hand, it won't help you unless you know what it is. Name the text file "title.asm". Then make sure it is in the same folder as the Tic Tac Toe game when you assemble it.

 

 ;                       title.asm

      .db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
      .db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
      .db 0,0,0,0,0,0,0,0,0,0,0,1,254,192,31,224,0,31,224,0,0,0,0,1,254,0,31,224,0,31,224
      .db 0,0,0,0,0,48,207,3,7,207,3,7,143,0,0,0,0,48,223,3,15,223,3,15,223,128,0,0,0,48,216
      .db 3,12,216,3,12,217,128,0,0,0,48,216,3,12,216,3,12,219,128,0,0,0,48,216,3,12,216,3,12,216,0
      .db 0,0,0,48,223,3,14,223,3,15,223,0,0,0,0,48,207,3,6,207,3,7,143,0,0,0,0,0,0,0,0
      .db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
      .db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
      .db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
      .db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
      .db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
      .db 0,0,0,0,0,0,0,0,0,3,192,0,0,0,1,128,0,0,0,0,0,1,32,0,0,0,0,128,0,0,0
      .db 0,0,3,96,0,0,0,1,128,0,0,0,0,0,2,108,198,97,172,145,38,72,0,0,0,0,3,149,40,128,82
      .db 145,73,72,0,0,0,0,6,51,236,195,247,179,159,216,0,0,0,0,4,34,4,68,165,35,16,144,0,0,0,0
      .db 4,34,68,68,164,194,146,96,0,0,0,0,30,115,187,135,237,134,220,207,192,0,0,0,0,0,0,0,1,0,0
      .db 128,0,0,0,0,0,0,0,0,2,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
      .db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
      .db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
      .db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
      .db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,2,12,0,0,0,0,0,0,0,0,0,0,6
      .db 18,0,0,0,0,0,0,0,0,0,0,6,54,0,0,0,0,0,0,34,107,60,214,4,36,0,0,0,0,0,0
      .db 34,149,69,41,4,36,0,0,0,0,0,0,61,252,111,123,12,108,0,0,0,0,0,0,41,8,42,82,8,72,0
      .db 0,0,0,0,0,17,40,42,82,8,72,0,0,0,0,0,0,49,221,219,182,63,112,0,0,0,0,0,0,0,0
      .db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
      .db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

 

Conclusion
    What do you think? Cool eh'? Pressing the "on" key seems to put the game into greyscale for some reason, oh well. If you think the title screen was cool, you can make them by using Bill Nagel's Pic83. Click here for instructions.

    This will be the last tutorial in this version of TI-83 Plus Asm tutorials v1.01. Don't worry though ,if you finish this tutorial early, look out for version 2.01 very soon (2 weeks).

 

Tutorial 16

    Cliquez pour revenir au menu du site... ou ici pour retourner au menu du tutorial.