2048 code

2048
You are encouraged to solve this taskaccording to the task description, using any language you may know.

Implement a 2D sliding block puzzle game where blocks with numbers are combined to add their values.

Rules of the game
•   The rules are that on each turn the player must choose a direction   (up, down, left or right).
•   All tiles move as far as possible in that direction, some move more than others.
•   Two adjacent tiles (in that direction only) with matching numbers combine into one bearing the sum of those numbers.
•   A move is valid when at least one tile can be moved,   if only by combination.
•   A new tile with the value of   2   is spawned at the end of each turn at a randomly chosen empty square   (if there is one).
•   Adding a new tile on a blank space.   Most of the time,   a new   2   is to be added,   and occasionally   (10% of the time),   a   4.
•   To win,   the player must create a tile with the number   2048.
•   The player loses if no valid moves are possible.

The name comes from the popular open-source implementation of this game mechanic, 2048.

Requirements
•   "Non-greedy" movement.
The tiles that were created by combining other tiles should not be combined again during the same turn (move).
That is to say,   that moving the tile row of:
[2][2][2][2]
to the right should result in:
......[4][4]
and not:
.........[8]
•   "Move direction priority".
If more than one variant of combining is possible,   move direction shall indicate which combination will take effect.
For example, moving the tile row of:
...[2][2][2]
to the right should result in:
......[2][4]
and not:
......[4][2]
•   Check for valid moves.   The player shouldn't be able to skip their turn by trying a move that doesn't change the board.
•   Check for a  win condition.
•   Check for a lose condition.

AArch64 Assembly

Works with: as version Raspberry Pi 3B version Buster 64 bits

/* ARM assembly AARCH64 Raspberry PI 3B */
/* program 2048_64.s */

/*******************************************/
/* Constantes file */
/*******************************************/
/* for this file see task include a file in language AArch64 assembly*/
.include "../includeConstantesARM64.inc"
.equ SIZE, 4
.equ TOTAL, 2048
.equ BUFFERSIZE, 80

.equ KEYSIZE, 8
.equ IOCTL, 0x1D // Linux syscall
.equ SIGACTION, 0x86 // Linux syscall
.equ SYSPOLL, 0x16 // Linux syscall
.equ CREATPOLL, 0x14 // Linux syscall
.equ CTLPOLL, 0x15 // Linux syscall

.equ TCGETS, 0x5401
.equ TCSETS, 0x5402
.equ ICANON, 2
.equ ECHO, 10
.equ POLLIN, 1

.equ SIGINT, 2 // Issued if the user sends an interrupt signal (Ctrl + C)
.equ SIGQUIT, 3 // Issued if the user sends a quit signal (Ctrl + D)
.equ SIGTERM, 15 // Software termination signal (sent by kill by default)
.equ SIGTTOU, 22

/*******************************************/
/* Structures */
/********************************************/
/* structure termios see doc linux*/
.struct 0
term_c_iflag: // input modes
.struct term_c_iflag + 4
term_c_oflag: // output modes
.struct term_c_oflag + 4
term_c_cflag: // control modes
.struct term_c_cflag + 4
term_c_lflag: // local modes
.struct term_c_lflag + 4
term_c_cc: // special characters
.struct term_c_cc + 40 // see length if necessary
term_fin:

/* structure sigaction see doc linux */
.struct 0
sa_handler:
.struct sa_handler + 8
sa_flags:
.struct sa_flags + 8
sa_sigaction:
.struct sa_sigaction + 8
sa_fin:

/* structure poll see doc linux */
.struct 0
.struct poll_event + 8
poll_fd: // events returned
.struct poll_fd + 8
poll_fin:
/*********************************/
/* Initialized data */
/*********************************/
.data
szMessOK: .asciz "Bravo !! You win. \n"
szMessNotOK: .asciz "You lost !! \n"
szMessNewGame: .asciz "New game (y/n) ? \n"
szMessErreur: .asciz "Error detected.\n"
szMessErrInitTerm: .asciz "Error terminal init.\n"
szMessErrInitPoll: .asciz "Error poll init.\n"
szMessErr: .asciz "Error code hexa : @ décimal : @ \n"
szCarriageReturn: .asciz "\n"
szMess0: .asciz " "
szMess2: .asciz " 2 "
szMess4: .asciz " 4 "
szMess8: .asciz " 8 "
szMess16: .asciz " 16 "
szMess32: .asciz " 32 "
szMess64: .asciz " 64 "
szMess128: .asciz " 128 "
szMess256: .asciz " 256 "
szMess512: .asciz " 512 "
szMess1024: .asciz " 1024 "
szMess2048: .asciz " 2048 "
szCleax1: .byte 0x1B
.byte 'c' // other console clear
.byte 0

szLineH: .asciz "-----------------------------\n"
szLineV: .asciz "|"
szLineVT: .asciz "| | | | |\n"
.align 4
/*********************************/
/* UnInitialized data */
/*********************************/
.bss
.align 4
sZoneConv: .skip 24
sBuffer: .skip BUFFERSIZE
qTbCase: .skip 8 * SIZE * SIZE
qEnd: .skip 8 // 0 loop 1 = end loop
qTouche: .skip KEYSIZE // value key pressed
stOldtio: .skip term_fin // old terminal state
stCurtio: .skip term_fin // current terminal state
stSigAction: .skip sa_fin // area signal structure
stSigAction1: .skip sa_fin
stSigAction2: .skip sa_fin
stSigAction3: .skip sa_fin
stPoll1: .skip poll_fin // area poll structure
stPoll2: .skip poll_fin
stevents: .skip 16
/*********************************/
/* code section */
/*********************************/
.text
.global main
main: // entry of program
mov x0,#0
bl initTerm // terminal init
cmp x0,0 // error ?
blt 100f
bl initPoll // epoll instance init
cmp x0,0
blt 99f
mov x22,x0 // save epfd
1: // begin game loop
bl affichageMess
bl razTable
2:
cmp x0,#-1
beq 5f // end game
bl displayGame
3:
mov x0,x22
bl waitKey
cmp x0,0
beq 3b
cmp x0,#-1
beq 99f // error
bl keyMove
cmp x0,#0
beq 3b // no change -> loop
cmp x0,#2 // last addition = 2048 ?
beq 4f
cmp x0,#-1 // quit ?
bne 2b // loop

b 10f
4: // last addition = 2048
bl affichageMess
b 10f
5: // display message no solution
bl affichageMess

10: // display new game ?
bl affichageMess
bl affichageMess
11:
mov x0,x22
bl waitKey
cmp x0,0
beq 11b
ldrb w0,[x0]
cmp w0,#'y'
beq 1b
cmp w0,#'Y'
beq 1b
99:
bl restauTerm // terminal restaur
100: // standard end of the program
mov x0, #0 // return code
mov x8, #EXIT // request to exit program
svc #0 // perform the system call

/******************************************************************/
/* raz table cases */
/******************************************************************/
razTable:
stp x0,lr,[sp,-16]! // save registres
stp x1,x2,[sp,-16]! // save registres
mov x2,#0
1:
str xzr,[x1,x2,lsl #3]
cmp x2,#SIZE * SIZE
blt 1b
100:
ldp x1,x2,[sp],16 // restaur des 2 registres
ldp x0,lr,[sp],16 // restaur des 2 registres
ret
/******************************************************************/
/* key move */
/******************************************************************/
/* x0 contains key value */
keyMove:
stp x1,lr,[sp,-16]! // save registres
lsr x0,x0,#16
cmp x0,#0x42 // down arrow
bne 1f
bl moveDown
b 100f
1:
cmp x0,#0x41 // high arrow
bne 2f
bl moveUp
b 100f
2:
cmp x0,#0x43 // right arrow
bne 3f
bl moveRight
b 100f
3:
cmp x0,#0x44 // left arrow
bne 4f
bl moveLeft
b 100f
4:
ldrb w0,[x0]
cmp w0,#'q' // quit game
bne 5f
mov x0,#-1
b 100f
5:
cmp w0,#'Q' // quit game
bne 100f
mov x0,#-1
b 100f

100:
ldp x1,lr,[sp],16 // restaur des 2 registres
ret
/******************************************************************/
/* move left */
/******************************************************************/
/* x0 return -1 if ok */
moveLeft:
stp x1,lr,[sp,-16]! // save registres
stp x2,x3,[sp,-16]! // save registres
stp x4,x5,[sp,-16]! // save registres
stp x6,x7,[sp,-16]! // save registres
stp x8,x9,[sp,-16]! // save registres
stp x10,x11,[sp,-16]! // save registres
mov x0,#0 // top move Ok
mov x2,#0 // line indice
1:
mov x6,#0 // counter empty case
mov x7,#0 // first digit
mov x10,#0 // last digit to add
mov x3,#0 // column indice
2:
lsl x5,x2,#2 // change this if size <> 4
add x5,x5,x3 // compute table indice
ldr x4,[x1,x5,lsl #3]
cmp x4,#0
cinc x6,x6,eq // positions vides
beq 5f
cmp x6,#0
beq 3f // no empty left case
mov x8,#0
str x8,[x1,x5,lsl #3] // raz digit
sub x5,x5,x6
str x4,[x1,x5,lsl #3] // and store to left empty position
mov x0,#1 // move Ok
3:
cmp x7,#0 // first digit
beq 4f
cmp x10,x4 // prec digit have to add
beq 4f
sub x8,x5,#1 // prec digit
ldr x9,[x1,x8,lsl #3]
cmp x4,x9 // equal ?
bne 4f
mov x10,x4 // save digit
str x4,[x1,x8,lsl #3]
cmp x4,#TOTAL
beq 6f
mov x4,#0
str x4,[x1,x5,lsl #3]
add x6,x6,#1 // empty case + 1
mov x0,#1 // move Ok
4:
add x7,x7,#1 // no first digit

5: // and loop
cmp x3,#SIZE
blt 2b
cmp x2,#SIZE
blt 1b
b 100f
6:
mov x0,#2 // total = 2048
100:
ldp x10,x11,[sp],16 // restaur des 2 registres
ldp x8,x9,[sp],16 // restaur des 2 registres
ldp x6,x7,[sp],16 // restaur des 2 registres
ldp x4,x5,[sp],16 // restaur des 2 registres
ldp x2,x3,[sp],16 // restaur des 2 registres
ldp x1,lr,[sp],16 // restaur des 2 registres
ret
/******************************************************************/
/* move right */
/******************************************************************/
/* x0 return -1 if ok */
moveRight:
stp x1,lr,[sp,-16]! // save registres
stp x2,x3,[sp,-16]! // save registres
stp x4,x5,[sp,-16]! // save registres
stp x6,x7,[sp,-16]! // save registres
stp x8,x9,[sp,-16]! // save registres
stp x10,x11,[sp,-16]! // save registres
mov x0,#0
mov x2,#0
1:
mov x6,#0
mov x7,#0
mov x10,#0
mov x3,#SIZE-1
2:
lsl x5,x2,#2 // change this if size <> 4
ldr x4,[x1,x5,lsl #3]
cmp x4,#0
cinc x6,x6,eq // positions vides
beq 5f

cmp x6,#0
beq 3f // no empty right case
mov x0,#0
str x0,[x1,x5,lsl #3] // raz digit
str x4,[x1,x5,lsl #3] // and store to right empty position
mov x0,#1
3:
cmp x7,#0 // first digit
beq 4f
ldr x9,[x1,x8,lsl #3]
cmp x4,x9 // equal ?
bne 4f
cmp x10,x4
beq 4f
mov x10,x4
str x4,[x1,x8,lsl #3]
cmp x4,#TOTAL
beq 6f
mov x4,#0
str x4,[x1,x5,lsl #3]
add x6,x6,#1 // empty case + 1
mov x0,#1
4:
add x7,x7,#1 // no first digit

5: // and loop
sub x3,x3,#1
cmp x3,#0
bge 2b
cmp x2,#SIZE
blt 1b
b 100f
6:
mov x0,#2
100:
ldp x10,x11,[sp],16 // restaur des 2 registres
ldp x8,x9,[sp],16 // restaur des 2 registres
ldp x6,x7,[sp],16 // restaur des 2 registres
ldp x4,x5,[sp],16 // restaur des 2 registres
ldp x2,x3,[sp],16 // restaur des 2 registres
ldp x1,lr,[sp],16 // restaur des 2 registres
ret
/******************************************************************/
/* move down */
/******************************************************************/
/* x0 return -1 if ok */
moveDown:
stp x1,lr,[sp,-16]! // save registres
stp x2,x3,[sp,-16]! // save registres
stp x4,x5,[sp,-16]! // save registres
stp x6,x7,[sp,-16]! // save registres
stp x8,x9,[sp,-16]! // save registres
stp x10,x11,[sp,-16]! // save registres
mov x0,#0
mov x3,#0
1:
mov x6,#0
mov x7,#0
mov x10,#0
mov x2,#SIZE-1
2:
lsl x5,x2,#2 // change this if size <> 4
ldr x4,[x1,x5,lsl #3]
cmp x4,#0
cinc x6,x6,eq // positions vides
beq 5f
cmp x6,#0
beq 3f // no empty right case
mov x0,#0
str x0,[x1,x5,lsl #3] // raz digit
lsl x0,x6,#2
str x4,[x1,x5,lsl #3] // and store to right empty position
mov x0,#1
3:
cmp x7,#0 // first digit
beq 4f
ldr x9,[x1,x8,lsl #3]
cmp x4,x9 // equal ?
bne 4f
cmp x10,x4
beq 4f
mov x10,x4
str x4,[x1,x8,lsl #3]
cmp x4,#TOTAL
beq 6f
mov x4,#0
str x4,[x1,x5,lsl #3]
add x6,x6,#1 // empty case + 1
mov x0,#1
4:
add x7,x7,#1 // no first digit

5: // and loop
sub x2,x2,#1
cmp x2,#0
bge 2b
cmp x3,#SIZE
blt 1b
b 100f
6:
mov x0,#2
100:
ldp x10,x11,[sp],16 // restaur des 2 registres
ldp x8,x9,[sp],16 // restaur des 2 registres
ldp x6,x7,[sp],16 // restaur des 2 registres
ldp x4,x5,[sp],16 // restaur des 2 registres
ldp x2,x3,[sp],16 // restaur des 2 registres
ldp x1,lr,[sp],16 // restaur des 2 registres
ret
/******************************************************************/
/* move up */
/******************************************************************/
/* x0 return -1 if ok */
moveUp:
stp x1,lr,[sp,-16]! // save registres
stp x2,x3,[sp,-16]! // save registres
stp x4,x5,[sp,-16]! // save registres
stp x6,x7,[sp,-16]! // save registres
stp x8,x9,[sp,-16]! // save registres
stp x10,x11,[sp,-16]! // save registres
mov x0,#0
mov x3,#0
1:
mov x6,#0
mov x7,#0
mov x10,#0
mov x2,#0
2:
lsl x5,x2,#2 // change this if size <> 4
ldr x4,[x1,x5,lsl #3]
cmp x4,#0
cinc x6,x6,eq // positions vides
beq 5f
cmp x6,#0
beq 3f // no empty right case
mov x0,#0
str x0,[x1,x5,lsl #3] // raz digit
lsl x0,x6,#2
sub x5,x5,x0
str x4,[x1,x5,lsl #3] // and store to right empty position
mov x0,#1
3:
cmp x7,#0 // first digit
beq 4f
sub x8,x5,#SIZE // up digit
ldr x9,[x1,x8,lsl #3]
cmp x4,x9 // equal ?
bne 4f
cmp x10,x4
beq 4f
mov x10,x4
str x4,[x1,x8,lsl #3]
cmp x4,#TOTAL
beq 6f
mov x4,#0
str x4,[x1,x5,lsl #3]
add x6,x6,#1 // empty case + 1
mov x0,#1
4:
add x7,x7,#1 // no first digit

5: // and loop
cmp x2,#SIZE
blt 2b
cmp x3,#SIZE
blt 1b
b 100f
6:
mov x0,#2
100:
ldp x10,x11,[sp],16 // restaur des 2 registres
ldp x8,x9,[sp],16 // restaur des 2 registres
ldp x6,x7,[sp],16 // restaur des 2 registres
ldp x4,x5,[sp],16 // restaur des 2 registres
ldp x2,x3,[sp],16 // restaur des 2 registres
ldp x1,lr,[sp],16 // restaur des 2 registres
ret
/******************************************************************/
/* add new digit on game */
/******************************************************************/
/* x0 return -1 if ok */
stp x1,lr,[sp,-16]! // save registres
stp x2,x3,[sp,-16]! // save registres
stp x4,x5,[sp,-16]! // save registres
sub sp,sp,#8 * SIZE*SIZE
mov fp,sp

mov x0,#100
bl genereraleas
cmp x0,#10
mov x1,#4
mov x5,#2
csel x5,x5,x1,ge
// movlt x5,#4
//movge x5,#2
mov x3,#0
mov x4,#0
1:
ldr x2,[x1,x3,lsl 3]
cmp x2,#0
bne 2f
str x3,[fp,x4,lsl 3]
2:
cmp x3,#SIZE*SIZE
blt 1b
cmp x4,#0 // no empty case
beq 4f
cmp x4,#1
bne 3f
ldr x2,[fp] // one case
str x5,[x1,x2,lsl 3]
mov x0,#0
b 100f
3: // multiple case
sub x0,x4,#1
bl genereraleas
ldr x2,[fp,x0,lsl 3]
str x5,[x1,x2,lsl 3]
mov x0,#0
b 100f
4:
mov x0,#-1
100:
add sp,sp,#8* (SIZE*SIZE) // stack alignement
ldp x4,x5,[sp],16 // restaur des 2 registres
ldp x2,x3,[sp],16 // restaur des 2 registres
ldp x1,lr,[sp],16 // restaur des 2 registres
ret
/******************************************************************/
/* display game */
/******************************************************************/
displayGame:
stp x1,lr,[sp,-16]! // save registres
stp x2,x3,[sp,-16]! // save registres
bl affichageMess
bl affichageMess
bl affichageMess
bl affichageMess
mov x2,#0
1:
ldr x0,[x1,x2,lsl #3]
bl digitString
bl affichageMess
bl affichageMess
cmp x2,#SIZE
blt 1b
bl affichageMess
bl affichageMess
bl affichageMess
bl affichageMess
bl affichageMess
2:
ldr x0,[x1,x2,lsl #3]
bl digitString
bl affichageMess
bl affichageMess
cmp x2,#SIZE*2
blt 2b
bl affichageMess
bl affichageMess
bl affichageMess
bl affichageMess
bl affichageMess
3:
ldr x0,[x1,x2,lsl #3]
bl digitString
bl affichageMess
bl affichageMess
cmp x2,#SIZE*3
blt 3b
bl affichageMess
bl affichageMess
bl affichageMess
bl affichageMess
bl affichageMess
4:
ldr x0,[x1,x2,lsl #3]
bl digitString
bl affichageMess
bl affichageMess
cmp x2,#SIZE*4
blt 4b
bl affichageMess
bl affichageMess
bl affichageMess

100:
ldp x2,x3,[sp],16 // restaur des 2 registres
ldp x1,lr,[sp],16 // restaur des 2 registres
ret
/******************************************************************/
/* digits string */
/******************************************************************/
/* x0 contains number */
/* x0 return address string */
digitString:
stp x1,lr,[sp,-16]! // save registres
cmp x0,#0
bne 1f
b 100f
1:
cmp x0,#2
bne 2f
b 100f
2:
cmp x0,#4
bne 3f
b 100f
3:
cmp x0,#8
bne 4f
b 100f
4:
cmp x0,#16
bne 5f
b 100f
5:
cmp x0,#32
bne 6f
b 100f
6:
cmp x0,#64
bne 7f
b 100f
7:
cmp x0,#128
bne 8f
b 100f
8:
cmp x0,#256
bne 9f
b 100f
9:
cmp x0,#512
bne 10f
b 100f
10:
cmp x0,#1024
bne 11f
b 100f
11:
cmp x0,#2048
bne 12f
b 100f
12:
bl displayError
100:
ldp x1,lr,[sp],16 // restaur des 2 registres
ret

/***************************************************/
/* Generation random number */
/***************************************************/
/* x0 contains limit */
genereraleas:
stp x1,lr,[sp,-16]! // save registers
stp x2,x3,[sp,-16]! // save registers
ldr x2,[x1]
ldr x3,qNbDep1
mul x2,x3,x2
ldr x3,qNbDep2
str x2,[x1] // maj de la graine pour l appel suivant
cmp x0,#0
beq 100f
udiv x3,x2,x0
msub x0,x3,x0,x2 // résult = remainder

100: // end function
ldp x2,x3,[sp],16 // restaur 2 registers
ldp x1,lr,[sp],16 // restaur 2 registers
/*****************************************************/

/******************************************************************/
/* traitement du signal */
/******************************************************************/
sighandler:
stp x0,lr,[sp,-16]! // save registers
str x1,[sp,-16]!
mov x1,#1 // maj zone end
str x1,[x0]
ldr x1,[sp],16
ldp x0,lr,[sp],16 // restaur 2 registers
/***************************************************/
/* display error message */
/***************************************************/
/* x0 contains error code x1 : message address */
displayError:
stp x2,lr,[sp,-16]! // save registers
mov x2,x0 // save error code
mov x0,x1
bl affichageMess
mov x0,x2 // error code
bl conversion16 // conversion hexa
ldr x0,qAdrszMessErr // display error message
bl strInsertAtCharInc // insert result at @ character
mov x3,x0
mov x0,x2 // error code
bl conversion10S // conversion decimale
mov x0,x3
bl strInsertAtCharInc // insert result at @ character
bl affichageMess
100:
ldp x2,lr,[sp],16 // restaur 2 registers
/*********************************/
/* init terminal state */
/*********************************/
initTerm:
stp x1,lr,[sp,-16]! // save registers
mov x0,STDIN // input console
mov x1,TCGETS
mov x8,IOCTL // call system Linux
svc 0
cbnz x0,98f // error ?

str x0,[x1,sa_handler] // maj handler
mov x0,SIGINT // signal type
mov x2,0
mov x3,8
mov x8,SIGACTION // call system
svc 0

cmp x0,0 // error ?
bne 98f
mov x0,SIGQUIT
mov x2,0 // NULL
mov x8,SIGACTION // call system
svc 0
cmp x0,0 // error ?
bne 98f
mov x0,SIGTERM
mov x2,0 // NULL
mov x8,SIGACTION // appel systeme
svc 0
cmp x0,0
bne 98f
//
str x0,[x1,sa_handler]
mov x0,SIGTTOU //invalidate other process signal
mov x2,0 // NULL
mov x8,SIGACTION // call system
svc 0
cmp x0,0
bne 98f
//
/* read terminal current state */
mov x0,STDIN
mov x1,TCGETS
mov x8,IOCTL // call systeme
svc 0
cmp x0,0 // error ?
bne 98f
mov x2,ICANON | ECHO // no key pressed echo on display
mvn x2,x2 // and one key
ldr x3,[x1,#term_c_lflag]
str x3,[x1,#term_c_lflag] // and store
mov x0,STDIN // maj terminal current state
mov x1,TCSETS
mov x8,IOCTL // call system
svc 0
cbz x0,100f
98: // error display
bl displayError
mov x0,-1
100:
ldp x1,lr,[sp],16 // restaur 2 registers
/*********************************/
/* init instance epool */
/*********************************/
initPoll:
stp x1,lr,[sp,-16]! // save registers
mov x1,STDIN // maj structure events
str x1,[x0,#poll_fd] // maj FD
mov x1,POLLIN // action code
str x1,[x0,#poll_event]
mov x0,0
mov x8,CREATPOLL // create epoll instance
svc 0
cmp x0,0 // error ?
ble 98f
mov x10,x0 // return FD epoll instance
mov x2,STDIN // Fd to we want add
mov x8,CTLPOLL // call system control epoll
svc 0
cmp x0,0 // error ?
blt 98f // no
mov x0,x10 // return FD epoll instance
b 100f
98: // error display
bl displayError
mov x0,-1
100:
ldp x1,lr,[sp],16 // restaur 2 registers
/*********************************/
/* wait key */
/*********************************/
/* x0 contains FD poll */
waitKey:
stp x1,lr,[sp,-16]! // save registers
str xzr,[x11] // raz key
1:
ldr x1,qAdrqEnd // if signal ctrl-c -> end
ldr x1,[x1]
cbnz x1,100f

mov x2,12 // size events
mov x3,1 // timeout = 1 TODO: ??
mov x4,0
mov x8,SYSPOLL // call system wait POLL
svc 0
cmp x0,0 // key pressed ?
bge 100f
98: // error display
bl displayError
mov x0,-1
100:
ldp x1,lr,[sp],16 // restaur 2 registers
/*********************************/
/*********************************/
/* x0 returns key value */
stp x1,lr,[sp,-16]! // save registers
mov x0,STDIN // File Descriptor
mov x2,KEYSIZE // key size
svc #0
cmp x0,0 // error ?
ble 98f
ldr x0,[x2]
b 100f
98: // error display
bl displayError
mov x0,-1
100:
ldp x1,lr,[sp],16 // restaur 2 registers
/*********************************/
/* restaur terminal state */
/*********************************/
restauTerm:
stp x1,lr,[sp,-16]! // save registers
mov x0,STDIN // end then restaur begin state terminal
mov x1,TCSETS
mov x8,IOCTL // call system
svc 0
cbz x0,100f
bl displayError
100:
ldp x1,lr,[sp],16 // restaur 2 registers
/********************************************************/
/* File Include fonctions */
/********************************************************/
/* for this file see task include a file in language AArch64 assembly */
.include "../includeARM64.inc"

Works with: GNAT

with System.Random_Numbers;
procedure Play_2048 is
-- ----- Keyboard management
type t_Keystroke is(Up, Down, Right, Left, Quit, Restart, Invalid);
-- Redefining this standard procedure as function to allow Get_Keystroke as an expression function
function Get_Immediate return Character is
begin
endreturn;
end Get_Immediate;
Arrow_Prefix : constant Character := Character'Val(224); -- works for windows
function Get_Keystroke return t_Keystroke is
(case Get_Immediate is
when 'Q' | 'q' => Quit,
when 'R' | 'r' => Restart,
when 'W' | 'w' => Left,
when 'A' | 'a' => Up,
when 'S' | 's' => Down,
when 'D' | 'd' => Right,
-- Windows terminal
when Arrow_Prefix => (case Character'Pos(Get_Immediate)is
when72 => Up,
when75 => Left,
when77 => Right,
when80 => Down,
whenothers => Invalid),
-- Unix escape sequences
when ASCII.ESC => (case Get_Immediate is
when '[' => (case Get_Immediate is
when 'A' => Up,
when 'B' => Down,
when 'C' => Right,
when 'D' => Left,
whenothers => Invalid),
whenothers => Invalid),
whenothers => Invalid);

-- ----- Game data
function Random_Int isnew System.Random_Numbers.Random_Discrete(Integer);
type t_List isarray(Positive range <>)of Natural;
subtype t_Row is t_List (1..4);
type t_Board isarray(1..4)of t_Row;
Board  : t_Board;
New_Board : t_Board;
Blanks  : Natural;
Score  : Natural;
Generator : System.Random_Numbers.Generator;

-- ----- Displaying the board
procedure Display_Board is
Horizontal_Rule : constant String := "+----+----+----+----+";
function Center (Value : in String)return String is
Value(Value'First+1..Value'Last) & -- Trim the leading space of the raw number image
(1..(2-Value'Length/2) => ' ')); -- Add trailing spaces
begin
Put_Line (Horizontal_Rule);
for Row of Board loop
for Cell of Row loop
Put('|' & (if Cell = 0then" "else Center(Cell'Img)));
endloop;
Put_Line("|");
Put_Line (Horizontal_Rule);
endloop;
Put_Line("Score =" & Score'Img);
end Display_Board;

-- ----- Game mechanics
Block_Offset : Positive := Random_Int(Generator, 1, Blanks);
begin
Blanks := Blanks-1;
for Row of Board loop
for Cell of Row loop
if Cell = 0then
if Block_Offset = 1then
Cell := (if Random_Int(Generator,1,10) = 1then4else2);
return;
else
Block_Offset := Block_Offset-1;
endif;
endif;
endloop;
endloop;

procedure Reset_Game is
begin
Board  := (others => (others => 0));
Blanks := 16;
Score  := 0;
end Reset_Game;

-- Moving and merging will always be performed leftward, hence the following transforms
function HFlip (What : in t_Row)return t_Row is
(What(4),What(3),What(2),What(1));
function VFlip (What : in t_Board)return t_Board is
(HFlip(What(1)),HFlip(What(2)),HFlip(What(3)),HFlip(What(4)));
function Transpose (What : in t_Board)return t_Board is
begin
for Row in t_Board'Rangeloop
for Column in t_Row'Rangeloop
endloop;
endloop;
endreturn;
end Transpose;

-- For moving/merging, recursive expression functions will be used, but they
-- can't contain statements, hence the following sub-function used by Merge
function Add_Blank (Delta_Score : in Natural)return t_List is
begin
Blanks := Blanks+1;
Score  := Score+Delta_Score;
return(1 => 0);

function Move_Row (What : in t_List)return t_List is
(if What'Length = 1then What
elsif What(What'First) = 0
then Move_Row(What(What'First+1..What'Last)) & (1 => 0)
else(1 => What(What'First)) & Move_Row(What(What'First+1..What'Last)));

function Merge (What : in t_List)return t_List is
(if What'Length <= 1orelse What(What'First) = 0then What
elsif What(What'First) = What(What'First+1)
then(1 => 2*What(What'First)) & Merge(What(What'First+2..What'Last)) & Add_Blank(What(What'First))
else(1 => What(What'First)) & Merge(What(What'First+1..What'Last)));

function Move (What : in t_Board)return t_Board is
(Merge(Move_Row(What(1))),Merge(Move_Row(What(2))),Merge(Move_Row(What(3))),Merge(Move_Row(What(4))));

begin
System.Random_Numbers.Reset(Generator);

Main_Loop: loop
Reset_Game;
Game_Loop: loop
Display_Board;
case Get_Keystroke is
when Restart => exit Game_Loop;
when Quit => exit Main_Loop;
when Left => New_Board := Move(Board);
when Right => New_Board := VFlip(Move(VFlip(Board)));
when Up => New_Board := Transpose(Move(Transpose(Board)));
when Down => New_Board := Transpose(VFlip(Move(VFlip(Transpose(Board)))));
whenothers => null;
endcase;

if New_Board = Board then
Put_Line ("Invalid move...");
elsif(for some Row of New_Board => (for some Cell of Row => Cell = 2048))then
Display_Board;
Put_Line ("Win !");
exit Main_Loop;
else
Board := New_Board;
Add_Block; -- OK since the board has changed
if Blanks = 0
andthen(forall Row in1..4 =>
(forall Column in1..3 =>
(Board(Row)(Column) /= Board(Row)(Column+1))))
andthen(forall Row in1..3 =>
(forall Column in1..4 =>
(Board(Row)(Column) /= Board(Row+1)(Column))))then
Display_Board;
Put_Line ("Lost !");
exit Main_Loop;
endif;
endif;
endloop Game_Loop;
endloop Main_Loop;
end Play_2048;
+----+----+----+----+ | 2 | 16 | 2 | 2 | +----+----+----+----+ | 64 | | | | +----+----+----+----+ | 4 | | | | +----+----+----+----+ | | | | | +----+----+----+----+ Score = 184

ALGOL 68

main:(
INT side = 4;
INT right = 1, up = 2, left = 3, down = 4;
[]CHAR direction letters ="ruld";
[]STRING direction descriptions =("right","up","left","down");

MODE BOARD =REF[,]INT;
MODE CELL =REFINT;

OP==(BOARD a, BOARD b)BOOL:
(FOR i TO side DOFOR j TO side DOIF a[i,j]/= b[i,j]THEN mismatch FIODOD;
TRUEEXIT
mismatch:FALSE);

PROC traverse board =(BOARD board,PROC(CELL)VOID callback)VOID:
FOR i FROM 1 LWB board TO 1 UPB board DO
FOR j FROM 2 LWB board TO 2 UPB board DO
callback(board[i,j])
ODOD;

PROC count blanks =(BOARD board)INT:
(INT count := 0;
traverse board(board,(CELL c)VOID:IF c = 0 THEN count +:= 1 FI);
count);

PROC nth blank=(BOARD board,INT nth) CELL:
(CELL result;
INT count := 0;
traverse board(board,(CELL c)VOID:
(IF c = 0 THEN count +:= 1 FI;
IF count = nth THEN
result := c; return
FI));
return: result);

PROC add new number =(BOARD board)VOID:
(INT nblanks = count blanks(board);
INT number :=(random >=.9| 4 | 2);
INT position :=ENTIER(random * nblanks)+ 1;

nth blank(board, position):= number);

PROC shift =(REF[]INT row,BOOL to the end)VOID:
(INT from =(to the end |UPB row |LWB row),
to =(to the end |LWB row |UPB row),
dir =(to the end |-1 | 1);
FOR i FROM from + dir BY dir TO to DO
IF row[i]/= 0 THEN
INTblank:= 0;
FOR j FROM i - dir BY-dir TO from WHILE row[j]= 0 DO
blank:= j
OD;
IFblank/= 0 THEN
row[blank]:= row[i];
row[i]:= 0
FI
FI
OD);

PROC combine =(REF[]INT row,BOOL to the end)VOID:
(INT from =(to the end |UPB row |LWB row),
to =(to the end |LWB row |UPB row),
dir =(to the end |-1 | 1);
FOR i FROM from BY dir TO to - dir DO
IF row[i]/= 0 AND row[i]= row[i+dir]THEN
row[i]*:= 2;
row[i+dir]:= 0
FI
OD);

PROC move =(BOARD board,INT direction)VOID:
FOR i TO side DO
CASE direction IN
# right #(shift(board[i,],TRUE); combine(board[i,],TRUE); shift(board[i,],TRUE)),
# up #(shift(board[,i],FALSE); combine(board[,i],FALSE); shift(board[,i],FALSE)),
# left #(shift(board[i,],FALSE); combine(board[i,],FALSE); shift(board[i,],FALSE)),
# down #(shift(board[,i],TRUE); combine(board[,i],TRUE); shift(board[,i],TRUE))
ESAC
OD;

PROCprint board =(BOARD board)VOID:
(FOR i FROM 1 LWB board TO 1 UPB board DO
print("+");
FOR j FROM 2 LWB board TO 2 UPB board DOprint("------+")OD;
print((new line,"|"));
FOR j FROM 2 LWB board TO 2 UPB board DO
print(((board[i,j]= 0 |" "|whole(board[i,j],-5))," |"))
OD;
print(new line)
OD;
print("+");FOR j FROM 2 LWB board TO 2 UPB board DOprint("------+")OD;
print(new line)
);

PROC score =(BOARD board)INT:
(INT result := 0;
traverse board(board,(CELL c)VOID: result +:= c);
result);

PROC join =([]STRING strings,STRING joiner)STRING:
IFUPB strings > 0 THEN
STRING result := strings[1];
FOR i FROM 2 TOUPB strings DO result +:= joiner +:= strings[i]OD;
result
ELSE
""
FI;

BOARD board =LOC[side,side]INT;
BOARD previous =LOC[side,side]INT;

traverse board(board,(CELL c)VOID: c := 0);

TO 2 DO add new number(board)OD;

# play! #
STRING prompt :="enter one of ["+ direction letters +"] (for "+ join(direction descriptions,"/")+"): ";
DO
CHAR key;
INT dir;
print board(board);
print(("score: ",whole(score(board),0),new line));
WHILE
print(prompt);
NOTchar in string(key, dir, direction letters)
DOSKIPOD;
previous := board;
move(board, dir);
IF count blanks(board)= 0 THEN lose FI;
traverse board(board,(CELL c)VOID:IF c = 2048 THEN win FI);
IF previous = board THEN
print(("try again!",new line))
ELSE
FI
OD;

win:print board(board);print(("you win!",new line))EXIT
lose:print(("you lose!",new line))
)

APPLESOFT

PRINT "Game 2048"

10 REM ************
20 REM * 2024 *
30 REM ************
40 HOME
100 W = 2: REM **** W=0 FOR LOOSE W=1 FOR WIN W=2 FOR PLAYING ****
110 DIM MA(4,4)
120 FC = 16: REM FREECELLS
130 A\$ = "":SC = 0:MT = 2
140 GOSUB 1000: DRAW THESCREEN
150 GOSUB 1500: REM PRINT SCORE AND MAXTILE
160 GOSUB 1700: REM BREED
170 GOSUB 2000: REM PRINT SCORES IN THE MATRIX AND CALC FC AND MT
200 REM ******************
210 REM MAIN PROGRAM
220 REM ******************
230 HTAB 38: VTAB 22
235 IF W < 2 THEN GOTO 950: REM ******* END GAME ********
240 WAIT - 16384,128:A = PEEK ( - 16384) - 128 - 68: POKE - 16368,0
250 ON A GOTO 999,900,900,900,300,350,400,900,450
280 REM ************************
285 REM FOLLOWING LINES HANDLE THE UP, LEFT, RIGHT, DOWN, NOP, EXIT
290 REM ************************
300 GOSUB 2500: GOSUB 3500: GOSUB 2500: GOSUB 1700: GOSUB 2000: GOSUB 1
500
310 GOTO 200
350 GOSUB 2600: GOSUB 3600: GOSUB 2600: GOSUB 1700: GOSUB 2000: GOSUB 1
500
360 GOTO 200
400 GOSUB 2700: GOSUB 3700: GOSUB 2700: GOSUB 1700: GOSUB 2000: GOSUB 1
500
410 GOTO 200
450 GOSUB 2800: GOSUB 3800: GOSUB 2800: GOSUB 1700: GOSUB 2000: GOSUB 1
500
460 GOTO 200
900 GOTO 200
950 HOME : VTAB 10
960 PRINT " ********************"
970 IF W = 1 THEN PRINT " * YOU WIN *"
980 IF W = 0 THEN PRINT " * YOU LOOSE *"
990 PRINT " ********************"
995 PRINT " SCORE =";SC
996 PRINT " MAXTILE=";MT
999 END
1000 REM DRAW FRAME + SCORE
1010 FOR I = 1 TO 5
1020 VTAB 1 + (I - 1) * 4: PRINT "---------------------"
1030 NEXT I
1040 FOR I = 1 TO 4
1050 FOR J = 1 TO 3
1060 VTAB 1 + (I - 1) * 4 + J: PRINT "| | | | |"
1070 NEXT J
1080 NEXT I
1090 HTAB 30: VTAB 3: PRINT "I";
1100 HTAB 30: VTAB 9: PRINT "M";
1110 HTAB 25: VTAB 6: PRINT "J";
1120 HTAB 35: VTAB 6: PRINT "K";
1130 HTAB 25: VTAB 12: PRINT "E = END"
1140 HTAB 25: VTAB 14: PRINT "SCORE:"
1150 HTAB 25: VTAB 16: PRINT "MAXTILE:"
1160 HTAB 1: VTAB 19: PRINT "YOU CAN SLIDE THE NUMBERS IN THE MATRIX"
1170 HTAB 1: VTAB 20: PRINT "BY PRESSING IJKM. WHEN MATCHING NUMBERS"
1180 HTAB 1: VTAB 21: PRINT "MEET THEY COMBINE IN THE SUM"
1190 HTAB 1: VTAB 22: PRINT "TO WIN YOU HAVE TO REACH THE SUM 2048"
1200 RETURN
1500 REM ***************
1501 REM PRINT SCORE + MAXTILE
1502 REM ***************
1510 VTAB 14: HTAB 32:
1520 SC\$ = STR\$ (SC):LS = LEN (SC\$)
1530 FOR I = 1 TO 7 - LS: PRINT " ";: NEXT I
1540 PRINT SC\$
1550 VTAB 16: HTAB 34:
1560 MT\$ = STR\$ (MT):LS = LEN (MT\$)
1570 FOR I = 1 TO 5 - LS: PRINT " ";: NEXT I
1580 PRINT MT\$
1590 IF SC = 2048 THEN W = 1: REM ******** YOU WIN ********
1690 RETURN
1700 REM ****************
1701 REM PUT A "2" IN A RANDOM EMPTY CELL
1702 REM ****************
1708 IF FC = 0 THEN W = 0: GOTO 1800: REM ***** YOU LOOSE *****
1710 K = INT ( RND (1) * FC + 1)
1720 N = 0
1730 FOR I = 1 TO 4
1740 FOR J = 1 TO 4
1750 IF MA(I,J) = 0 THEN N = N + 1
1760 IF N = K THEN MA(I,J) = 2:FC = FC - 1:I = 4:J = 4
1780 NEXT J
1790 NEXT I
1800 RETURN
2000 REM *************
2001 REM WRITE THE CELL CONTENT AND CALC. FREECELLS AND MAXTILE
2002 REM *************
2005 FC = 0:MT = 0: REM INITIALIZE FREECELLS AND MAXTILES
2010 FOR I = 1 TO 4
2020 FOR J = 1 TO 4
2030 HTAB 2 + (J - 1) * 5: VTAB 3 + (I - 1) * 4
2040 PRINT " ";: HTAB 2 + (J - 1) * 5
2050 IF MA(I,J) = 0 THEN FC = FC + 1: GOTO 2060
2055 PRINT MA(I,J);
2060 IF MA(I,J) > MT THEN MT = MA(I,J)
2090 NEXT J
2100 NEXT I
2190 RETURN
2500 REM *****************
2510 REM COMPACT UP - KIND OF BUBBLE SORT
2520 REM *****************
2530 FOR J = 1 TO 4
2540 FOR K = 3 TO 1 STEP - 1
2550 FOR I = 1 TO K
2560 IF MA(I,J) = 0 THEN MA(I,J) = MA(I + 1,J):MA(I + 1,J) = 0
2570 NEXT : NEXT : NEXT
2590 RETURN
2600 REM ************
2610 REM COMPACT LEFT
2620 REM ************
2630 FOR I = 1 TO 4
2640 FOR K = 3 TO 1 STEP - 1
2650 FOR J = 1 TO K
2660 IF MA(I,J) = 0 THEN MA(I,J) = MA(I,J + 1):MA(I,J + 1) = 0
2670 NEXT : NEXT : NEXT
2690 RETURN
2700 REM ************
2710 REM COMPACT RIGHT
2720 REM ************
2730 FOR I = 1 TO 4
2740 FOR K = 2 TO 4
2750 FOR J = 4 TO K STEP - 1
2760 IF MA(I,J) = 0 THEN MA(I,J) = MA(I,J - 1):MA(I,J - 1) = 0
2770 NEXT : NEXT : NEXT
2790 RETURN
2800 REM *****************
2810 REM COMPACT DOWN
2820 REM *****************
2830 FOR J = 1 TO 4
2840 FOR K = 2 TO 4
2850 FOR I = 4 TO K STEP - 1
2860 IF MA(I,J) = 0 THEN MA(I,J) = MA(I - 1,J):MA(I - 1,J) = 0
2870 NEXT : NEXT : NEXT
2890 RETURN
3500 REM ***************
3520 REM ***************
3530 FOR J = 1 TO 4
3540 FOR I = 1 TO 3
3550 IF MA(I,J) = MA(I + 1,J) THEN MA(I,J) = MA(I,J) * 2:MA(I + 1,J) =
0:SC = SC + MA(I,J)
3560 NEXT : NEXT
3590 RETURN
3600 REM **************
3610 REM SUM LEFT
3620 REM **************
3630 FOR I = 1 TO 4
3640 FOR J = 1 TO 3
3650 IF MA(I,J) = MA(I,J + 1) THEN MA(I,J) = MA(I,J) * 2:MA(I,J + 1) =
0:SC = SC + MA(I,J)
3660 NEXT : NEXT
3690 RETURN
3700 REM **************
3710 REM SUM RIGHT
3720 REM **************
3730 FOR I = 1 TO 4
3740 FOR J = 4 TO 2 STEP - 1
3750 IF MA(I,J) = MA(I,J - 1) THEN MA(I,J) = MA(I,J) * 2:MA(I,J - 1) =
0:SC = SC + MA(I,J)
3760 NEXT : NEXT
3790 RETURN
3800 REM ***************
3820 REM ***************
3830 FOR J = 1 TO 4
3840 FOR I = 4 TO 2 STEP - 1
3850 IF MA(I,J) = MA(I - 1,J) THEN MA(I,J) = MA(I,J) * 2:MA(I - 1,J) =
0:SC = SC + MA(I,J)
3860 NEXT : NEXT
3890 RETURN

-----
it runs somehow slowly but still fun to play. The only non standard basic is the input routine which reads directly the memory location (line 240) instead of using "input" od "get"

---------------------
| | | | |
|4 | | |2 | I
| | | | |
---------------------
| | | | | J K
|4 |2 | | |
| | | | |
--------------------- M
| | | | |
|2 |16 |4 | |
| | | | | E = END
---------------------
| | | | | SCORE: 4924
|128 |512 | | |
| | | | | MAXTILE: 512
---------------------

YOU CAN SLIDE THE NUMBERS IN THE MATRIX
BY PRESSING IJKM. WHEN MATCHING NUMBERS
MEET THEY COMBINE IN THE SUM
TO WIN YOU HAVE TO REACH THE SUM 2048

ARM Assembly

Works with: as version Raspberry Pi

/* ARM assembly Raspberry PI */
/* program 2048.s */

/* REMARK 1: this program use routines in a include file
see task Include a file language arm assembly
for the routine affichageMess conversion10
see at end of this program the instruction include */
/* for constantes see task include a file in arm assembly */
/************************************/
/* Constantes */
/************************************/
.include "../constantes.inc"
.equ STDIN,0 @ Linux input console
.equ SIZE,4
.equ TOTAL,2048
.equ BUFFERSIZE,80

.equ IOCTL,0x36 @ Linux syscall
.equ SIGACTION,0x43 @ Linux syscall
.equ SYSPOLL,0xA8 @ Linux syscall

.equ TCGETS,0x5401
.equ TCSETS,0x5402
.equ ICANON,2
.equ ECHO,10
.equ POLLIN,1

.equ SIGINT,2 @ Issued if the user sends an interrupt signal (Ctrl + C)
.equ SIGQUIT,3 @ Issued if the user sends a quit signal (Ctrl + D)
.equ SIGTERM,15 @ Software termination signal (sent by kill by default)
.equ SIGTTOU,22

/*******************************************/
/* Structures */
/********************************************/
/* structure termios see doc linux*/
.struct 0
term_c_iflag: @ input modes
.struct term_c_iflag +4
term_c_oflag: @ output modes
.struct term_c_oflag +4
term_c_cflag: @ control modes
.struct term_c_cflag +4
term_c_lflag: @ local modes
.struct term_c_lflag +4
term_c_cc: @ special characters
.struct term_c_cc +20 @ see length if necessary
term_fin:

/* structure sigaction see doc linux */
.struct 0
sa_handler:
.struct sa_handler +4
sa_flags:
.struct sa_flags +4
sa_sigaction:
.struct sa_sigaction +4
sa_fin:

/* structure poll see doc linux */
.struct 0
poll_fd: @ File Descriptor
.struct poll_fd +4
.struct poll_events +4
poll_revents: @ events returned
.struct poll_revents +4
poll_fin:
/*********************************/
/* Initialized data */
/*********************************/
.data
szMessOK:.asciz "Bravo !! You win. \n"
szMessNotOK:.asciz "You lost !! \n"
szMessNewGame:.asciz "New game (y/n) ? \n"
szMessErreur:.asciz "Error detected.\n"
szCarriageReturn:.asciz "\n"
//szMessMovePos:.asciz "\033[00;00H"
szMess0:.asciz " "
szMess2:.asciz " 2 "
szMess4:.asciz " 4 "
szMess8:.asciz " 8 "
szMess16:.asciz " 16 "
szMess32:.asciz " 32 "
szMess64:.asciz " 64 "
szMess128:.asciz " 128 "
szMess256:.asciz " 256 "
szMess512:.asciz " 512 "
szMess1024:.asciz " 1024 "
szMess2048:.asciz " 2048 "
szClear1:.byte 0x1B
.byte 'c' @ other console clear
.byte 0

szLineH:.asciz "-----------------------------\n"
szLineV:.asciz "|"
szLineVT:.asciz "| | | | |\n"
.align 4
iGraine:.int 123456
/*********************************/
/* UnInitialized data */
/*********************************/
.bss
.align 4
sZoneConv:.skip 24
sBuffer:.skip BUFFERSIZE
iTbCase:.skip 4* SIZE * SIZE
iEnd:.skip 4 @ 0 loop 1 = end loop
iTouche:.skip 4 @ value key pressed
stOldtio:.skip term_fin @ old terminal state
stCurtio:.skip term_fin @ current terminal state
stSigAction:.skip sa_fin @ area signal structure
stSigAction1:.skip sa_fin
stPoll1:.skip poll_fin @ area poll structure
stPoll2:.skip poll_fin
/*********************************/
/* code section */
/*********************************/
.text
.global main
main: @ entry of program

1: @ begin game loop
bl affichageMess
bl razTable
2:
cmpr0,#-1
beq5f @ end game
bl displayGame
3:
cmpr0,#-1
beq100f @ error or control-c
bl keyMove
cmpr0,#0
beq 3b @ no change -> loop
cmpr0,#2 @ last addition = 2048 ?
beq4f
cmpr0,#-1 @ quit ?
bne 2b @ loop

b10f
4: @ last addition = 2048
bl affichageMess
b10f
5: @ display message no solution
bl affichageMess

10: @ display new game ?
bl affichageMess
bl affichageMess
ldrbr0,[r0]
cmpr0,#'y'
beq1b
cmpr0,#'Y'
beq1b

100: @ standard end of the program
movr0, #0 @ return code
movr7, #EXIT @ request to exit program
svc #0 @ perform the system call

/******************************************************************/
/* raz table cases */
/******************************************************************/
razTable:
push{r0-r2,lr} @ save registers
movr0,#0
movr2,#0
1:
strr0,[r1,r2,lsl #2]
cmpr2,#SIZE * SIZE
blt1b
100:
pop{r0-r2,lr} @ restaur registers
bxlr @return
/******************************************************************/
/* key move */
/******************************************************************/
/*r0 contains key value */
keyMove:
push{r1,lr} @ save registers
cmpr0,#0x42 @ down arrow
bne1f
bl moveDown
b100f
1:
cmpr0,#0x41 @ high arrow
bne2f
bl moveUp
b100f
2:
cmpr0,#0x43 @ right arrow
bne3f
bl moveRight
b100f
3:
cmpr0,#0x44 @ left arrow
bne4f
bl moveLeft
b100f
4:
ldrbr0,[r0]
cmpr0,#'q' @ quit game
bne5f
movr0,#-1
b100f
5:
cmpr0,#'Q' @ quit game
bne100f
movr0,#-1
b100f

100:
pop{r1,lr} @ restaur registers
bxlr @return
/******************************************************************/
/* move left */
/******************************************************************/
/*r0 return -1 if ok */
moveLeft:
push{r1-r10,lr} @ save registers
movr0,#0 @ top move Ok
movr2,#0 @ line indice
1:
movr6,#0 @ counter empty case
movr7,#0 @ first digit
movr10,#0 @ last digit to add
movr3,#0 @ column indice
2:
lslr5,r2,#2 @ change this if size <> 4
ldrr4,[r1,r5,lsl #2]
cmpr4,#0
beq5f
cmpr6,#0
beq3f @ no empty left case
movr8,#0
strr8,[r1,r5,lsl #2] @ raz digit
subr5,r5,r6
strr4,[r1,r5,lsl #2] @ and store to left empty position
movr0,#1 @ move Ok
//subr6,r6,#1
3:
cmpr7,#0 @ first digit
beq4f
cmpr10,r4 @ prec digit have to add
beq4f
subr8,r5,#1 @ prec digit
ldrr9,[r1,r8,lsl #2]
cmpr4,r9 @ equal ?
bne4f
movr10,r4 @ save digit
strr4,[r1,r8,lsl #2]
cmpr4,#TOTAL
moveqr0,#2
beq100f
movr4,#0
strr4,[r1,r5,lsl #2]
movr0,#1 @ move Ok
4:

5: @ and loop
cmpr3,#SIZE
blt 2b
cmpr2,#SIZE
blt1b
100:
pop{r1-r12,lr}
bxlr @ return
/******************************************************************/
/* move right */
/******************************************************************/
/*r0 return -1 if ok */
moveRight:
push{r1-r5,lr} @ save registers
movr0,#0
movr2,#0
1:
movr6,#0
movr7,#0
movr10,#0
movr3,#SIZE-1
2:
lslr5,r2,#2 @ change this if size <> 4
ldrr4,[r1,r5,lsl #2]
cmpr4,#0
beq5f

cmpr6,#0
beq3f @ no empty right case
movr0,#0
strr0,[r1,r5,lsl #2] @ raz digit
strr4,[r1,r5,lsl #2] @ and store to right empty position
movr0,#1
3:
cmpr7,#0 @ first digit
beq4f
ldrr9,[r1,r8,lsl #2]
cmpr4,r9 @ equal ?
bne4f
cmpr10,r4
beq4f
movr10,r4
strr4,[r1,r8,lsl #2]
cmpr4,#TOTAL
moveqr0,#2
beq100f
movr4,#0
strr4,[r1,r5,lsl #2]
movr0,#1
4:

5: @ and loop
subr3,r3,#1
cmpr3,#0
bge 2b
cmpr2,#SIZE
blt1b

100:
pop{r1-r5,lr}
bxlr @ return
/******************************************************************/
/* move down */
/******************************************************************/
/*r0 return -1 if ok */
moveDown:
push{r1-r5,lr} @ save registers
movr0,#0
movr3,#0
1:
movr6,#0
movr7,#0
movr10,#0
movr2,#SIZE-1
2:
lslr5,r2,#2 @ change this if size <> 4
ldrr4,[r1,r5,lsl #2]
cmpr4,#0
beq5f
cmpr6,#0
beq3f @ no empty right case
movr0,#0
strr0,[r1,r5,lsl #2] @ raz digit
lslr0,r6,#2
strr4,[r1,r5,lsl #2] @ and store to right empty position
movr0,#1
3:
cmpr7,#0 @ first digit
beq4f
ldrr9,[r1,r8,lsl #2]
cmpr4,r9 @ equal ?
bne4f
cmpr10,r4
beq4f
movr10,r4
strr4,[r1,r8,lsl #2]
cmpr4,#TOTAL
moveqr0,#2
beq100f
movr4,#0
strr4,[r1,r5,lsl #2]
movr0,#1
4:

5: @ and loop
subr2,r2,#1
cmpr2,#0
bge 2b
cmpr3,#SIZE
blt1b

100:
pop{r1-r5,lr}
bxlr @ return
/******************************************************************/
/* move up */
/******************************************************************/
/*r0 return -1 if ok */
moveUp:
push{r1-r5,lr} @ save registers
movr0,#0
movr3,#0
1:
movr6,#0
movr7,#0
movr10,#0
movr2,#0
2:
lslr5,r2,#2 @ change this if size <> 4
ldrr4,[r1,r5,lsl #2]
cmpr4,#0
beq5f
cmpr6,#0
beq3f @ no empty right case
movr0,#0
strr0,[r1,r5,lsl #2] @ raz digit
lslr0,r6,#2
subr5,r5,r0
strr4,[r1,r5,lsl #2] @ and store to right empty position
movr0,#1
3:
cmpr7,#0 @ first digit
beq4f
subr8,r5,#SIZE @ up digit
ldrr9,[r1,r8,lsl #2]
cmpr4,r9 @ equal ?
bne4f
cmpr10,r4
beq4f
movr10,r4
strr4,[r1,r8,lsl #2]
cmpr4,#TOTAL
moveqr0,#2
beq100f
movr4,#0
strr4,[r1,r5,lsl #2]
movr0,#1
4:

5: @ and loop
cmpr2,#SIZE
blt 2b
cmpr3,#SIZE
blt1b

100:
pop{r1-r5,lr}
bxlr @ return
/******************************************************************/
/*add new digit on game */
/******************************************************************/
/*r0 return -1 if ok */
push{r1-r5,lr} @ save registers
subsp,#4* SIZE*SIZE
movfp,sp

movr0,#100
bl genereraleas
cmpr0,#10
movltr5,#4
movger5,#2
movr3,#0
movr4,#0
1:
ldrr2,[r1,r3,lsl #2]
cmpr2,#0
bne2f
strr3,[fp,r4,lsl #2]
2:
cmpr3,#SIZE*SIZE
blt1b
cmpr4,#0 @ no empty case
moveqr0,#-1
beq100f
cmpr4,#1
bne3f
ldrr2,[fp] @ one case
strr5,[r1,r2,lsl #2]
movr0,#0
b100f
3: @ multiple case
subr0,r4,#1
bl genereraleas
ldrr2,[fp,r0,lsl #2]
strr5,[r1,r2,lsl #2]
movr0,#0

100:
pop{r1-r5,lr}
bxlr @ return
/******************************************************************/
/* display game */
/******************************************************************/
displayGame:
push{r1-r3,lr} @ save registers
bl affichageMess
bl affichageMess
bl affichageMess
bl affichageMess
movr2,#0
1:
ldrr0,[r1,r2,lsl #2]
bl digitString
bl affichageMess
bl affichageMess
cmpr2,#SIZE
blt1b
bl affichageMess
bl affichageMess
bl affichageMess
bl affichageMess
bl affichageMess
2:
ldrr0,[r1,r2,lsl #2]
bl digitString
bl affichageMess
bl affichageMess
cmpr2,#SIZE*2
blt 2b
bl affichageMess
bl affichageMess
bl affichageMess
bl affichageMess
bl affichageMess
3:
ldrr0,[r1,r2,lsl #2]
bl digitString
bl affichageMess
bl affichageMess
cmpr2,#SIZE*3
blt 3b
bl affichageMess
bl affichageMess
bl affichageMess
bl affichageMess
bl affichageMess
4:
ldrr0,[r1,r2,lsl #2]
bl digitString
bl affichageMess
bl affichageMess
cmpr2,#SIZE*4
blt 4b
bl affichageMess
bl affichageMess
bl affichageMess

100:
pop{r1-r3,lr}
bxlr @ return
/******************************************************************/
/* digits string */
/******************************************************************/
/*r0 contains number */
digitString:
push{r1,lr} @ save registers
cmpr0,#0
bne1f
b100f
1:
cmpr0,#2
bne2f
b100f
2:
cmpr0,#4
bne3f
b100f
3:
cmpr0,#8
bne4f
b100f
4:
cmpr0,#16
bne5f
b100f
5:
cmpr0,#32
bne6f
b100f
6:
cmpr0,#64
bne7f
b100f
7:
cmpr0,#128
bne8f
b100f
8:
cmpr0,#256
bne9f
b100f
9:
cmpr0,#512
bne10f
b100f
10:
cmpr0,#1024
bne11f
b100f
11:
cmpr0,#2048
bne12f
b100f
12:
bl displayError
100:
pop{r1,lr}
bxlr @ return

/***************************************************/
/* Generation random number */
/***************************************************/
/*r0 contains limit */
genereraleas:
push{r1-r4,lr} @ save registers
ldrr2,[r4]
ldrr3,iNbDep1
mulr2,r3,r2
ldrr3,iNbDep2
strr2,[r4] @ maj de la graine pour l appel suivant
cmpr0,#0
beq100f
movr0,r2 @ dividende
bl division
movr0,r3 @ résult = remainder

100: @ end function
pop{r1-r4,lr} @ restaur registers
bxlr @ return
/*****************************************************/
iNbDep1:.int 0x343FD
iNbDep2:.int 0x269EC3
/***************************************************/
/***************************************************/
push{r1-r7,lr}
movr5,#0
strr5,[r1] @ raz
Sours: https://rosettacode.org/wiki/2048

2048 Game in Python

In this article we will look python code and logic to design a 2048 game you have played very often in your smartphone. If you are not familiar with the game, it is highly recommended to first play the game so that you can understand the basic functioning of it.

How to play 2048 :

Attention geek! Strengthen your foundations with the Python Programming Foundation Course and learn the basics.

To begin with, your interview preparations Enhance your Data Structures concepts with the Python DS Course. And to begin with your Machine Learning Journey, join the Machine Learning - Basic Level Course

1. There is a 4*4 grid which can be filled with any number. Initially two random cells are filled with 2 in it. Rest cells are empty.

2. we have to press any one of four keys to move up, down, left, or right. When we press any key, the elements of the cell move in that direction such that if any two identical numbers are contained in that particular row (in case of moving left or right) or column (in case of moving up and down) they get add up and extreme cell in that direction fill itself with that number and rest cells goes empty again.

3. After this grid compression any random empty cell gets itself filled with 2.

4. Following the above process we have to double the elements by adding up and make 2048 in any of the cell. If we are able to do that we wins.

5. But if during the game there is no empty cell left to be filled with a new 2, then the game goes over.

In above process you can see the snapshots from graphical user interface of 2048 game. But all the logic lies in the main code. So to solely understand the logic behind it we can assume the above grid to be a 4*4 matrix ( a list with four rows and four columns). You can see below the way to take input and output without GUI for the above game.

Example :

Commands are as follows : 'W' or 'w' : Move Up 'S' or 's' : Move Down 'A' or 'a' : Move Left 'D' or 'd' : Move Right [0, 0, 0, 0] [0, 0, 0, 0] [0, 0, 0, 0] [0, 0, 2, 0] Press the command : a GAME NOT OVER [0, 0, 0, 2] [0, 0, 0, 0] [0, 0, 0, 0] [2, 0, 0, 0] Press the command : s GAME NOT OVER [0, 0, 0, 0] [0, 0, 0, 0] [0, 0, 2, 0] [2, 0, 0, 2] Press the command : d GAME NOT OVER [0, 0, 0, 0] [0, 0, 0, 0] [2, 0, 0, 2] [0, 0, 0, 4] Press the command : a GAME NOT OVER [0, 2, 0, 0] [0, 0, 0, 0] [4, 0, 0, 0] [4, 0, 0, 0] Press the command : s GAME NOT OVER [0, 0, 0, 0] [0, 0, 0, 0] [0, 0, 0, 0] [8, 2, 0, 2] . . . And the series of input output will go on till we lose or win!

Programming Approach :

1. We will design each logic function such as we are performing a left swipe then we will use it for right swipe by reversing matrix and performing left swipe.
2. Moving up can be done by taking transpose then moving left.
3. Moving down can be done by taking transpose the moving right.
4. All the logic in the program are explained in detail in the comments. Highly recommended to go through all the comments.

We have two python files below, one is 2048.py which contains main driver code and the other is logic.py which contains all functions used. logic.py should be imported in 2048.py to use these functions. just place both the files in the same folder then run 2048.py will work perfectly.

logic.py

2048.py

Python3

Output :

My Personal Notesarrow_drop_up
Sours: https://www.geeksforgeeks.org/2048-game-in-python/

2048

A small clone of 1024, based on Saming's 2048 (also a clone).

Made just for fun. Play it here!

The official app can also be found on the Play Store and App Store!

Contributions

Anna Harren and sigod are maintainers for this repository.

Other notable contributors:

Many thanks to rayhaanj, Mechazawa, grant, remram44 and ghoullier for the many other good contributions.

Screenshot

That screenshot is fake, by the way. I never reached 2048

Contributing

Changes and improvements are more than welcome! Feel free to fork and open a pull request. Please make your changes in a specific branch and request to pull into ! If you can, please make sure the game fully works before sending the PR, as that will help speed up the process.

You can find the same information in the contributing guide.

Donations

I made this in my spare time, and it's hosted on GitHub (which means I don't have any hosting costs), but if you enjoyed the game and feel like buying me coffee, you can donate at my BTC address: . Thank you very much!

Sours: https://github.com/gabrielecirulli/2048

Half an hour later, the body on the bike was riding towards me. Zoya. - I already meet the second bus. Have you brought the wine.

Code 2048

Her life. In one of the packages, I unexpectedly noticed the same Svetkin training suit. And something exploded in me. It got hot, easy and somehow.

How to redeem diamonds from 2048 cube winner - 2048 CUBE WINNER APP REAL OR FAKE WINNER FREE FIRE

Envy. Vika laughed. And I liked to empty his balls with you like this. After you, the taste of his semen is completely different. Some kind of saturated and more liquid.

Now discussing:

I could swear it was my damaged guide. They followed me. Chapter 6 Creena slept. I kicked off my shoes at the door, tiptoed into the room, closed the door and lit the candles.

261 262 263 264 265