/*
* File: Snake.cpp
* Creator: H3Sjunior
*
* Tro choi con ran san moi
*/
// Y tuong:
// - con ran di chuyen trong phan gioi han, an thuc an, tranh cac chuong ngai vat
// - dung danh sach lien ket
// - moi nut cua danh sach lien ket la mot nut cua con ran: du lieu ve vi tri, con tro chi ve nut phia sau cua no
// - cach thuc di chuyen: in tat ca vi tri cac nut, thoi gian cho nguoi dung nhap huong di chuyen, xoa man hinh, in tat ca vi tri cac nut sau khi di chuyen
#include <iostream>
#include <conio.h>
#include <windows.h>
#include <ctime>
#include <cstdlib>
// Dinh nghia cac phim di chuyen tren ban phim: a, d, w, s
#define KEY_A 0x41
#define KEY_D 0x44
#define KEY_W 0x57
#define KEY_S 0x53
using namespace std;
// duong bien gioi han con ran co the di chuyen
const int TUNG_DO = 20 ;
const int HOANG_DO = 60 ;
// tao vi tri moi
struct viTri {
int x;
int y;
} ;
// danh sach lien ket cac nut cua con ran
struct snake{
viTri data;
snake * next;
} ;
void gotoxy( short x, short y) ; // ham gotoxy: dua con tro toi vi tri (x, y)
viTri newNoc ( int x, int y) ; // tao vi tri cua 1 nut
void addHead ( snake * & head, int x, int y) ; // tao nut con ran moi
void addEnd ( snake * & head, int x, int y) ; // chep du lieu vi tri vao nut moi cua con ran ( khi an duoc thuc an)
int length ( snake * & head) ; // do dai cua ran
void copy ( snake * & head1, snake * & head2) ; // sao chep vi tri nut 2 vao nut 1
void background ( snake * & head) ; // tao phong nen de choi game
void atime ( long & doKho, int & control1, int & control2) ; // thoi gian dung cua con ran, nut con control la A, W, S, D de chi huong di chuyen
void movieSnake ( snake * & head, int & control1, int & control2) ; // di chuyen con ran = di chuyen lan luot tung nut cua con ran (*)
void print ( snake * & head) ; // in ca con ran sau khi xoa man hinh
bool checkKey( int key) ; // trong time chay kiem tra co an nut di chuyen hay ko
void xoaMH ( ) ; // xoa man hinh
bool isMovie( snake * & head, snake * & ghost, int & score) ; // dieu kien di chuyen: ko dam trung duoi, ko dam trung tuong
void theEnd ( snake * & head, int & score) ; // in man hinh ket thuc game
bool newFood ( viTri & food) ; // tao thuc an moi
void checkEat ( snake * & head, snake * & ghost, viTri & food, int & score) ; // Kiem tra ran co an duoc thuc an hay khong
void level ( long & doKho) ; // Chia do kho cua game, tuy theo toc do di chuyen cua con ran
void ghost ( snake * & ghost, int & runGhost) ; // tao chuong ngai vat di chuyen tu tren xuong, ran dam trung thi se thua
void printGhost ( snake * & ghost) ; // in chuong ngai vat
void deleteSnake ( snake * & head) ; // xoa con ran sau khi game ket thuc, ham nay dang hoan thien
int main ( )
{
int playAgain = 0 ;
int control1 ; // lenh dieu khien truoc do
int control2; // lenh dieu khien sau
int i = 0 , end = 0 , score = 0 , runGhost = 0 ;
viTri food;
long doKho;
int bestScore = 0 ;
do
{
snake * Snake; // con ran
snake * Ghost; // chuong ngai vat
Snake = NULL ;
Ghost = NULL ;
addHead ( Snake, 2 , 5 ) ;
addHead ( Snake, 3 , 5 ) ;
addHead ( Snake, 4 , 5 ) ;
addHead ( Snake, 5 , 5 ) ;
addHead ( Snake, 6 , 5 ) ;
background ( Snake) ; // tao khung nen cua chuong trinh
score = length( Snake) ;
control1 = control2 = 3 ;
xoaMH ( ) ;
level ( doKho) ;
print ( Snake) ;
newFood ( food) ;
while ( 1 ) {
if ( isMovie ( Snake, Ghost, score) ) {
gotoxy( 1 , 23 ) ;
system ( "pause" ) ;
break ;
}
checkEat ( Snake, Ghost, food, score) ;
atime ( doKho, control1, control2) ;
movieSnake ( Snake, control2, control1) ;
control1 = control2;
xoaMH ( ) ;
print ( Snake) ;
ghost ( Ghost, runGhost) ;
printGhost ( Ghost) ;
runGhost++ ;
}
xoaMH ( ) ;
gotoxy ( 20 , 5 ) ;
cout << "1. Play again" ;
gotoxy ( 20 , 6 ) ;
cout << "2. Back" ;
gotoxy ( 14 , 8 ) ;
cout << "Please choose number (1->2): " ;
cin >> playAgain;
if ( playAgain == 1 ) {
deleteSnake( Snake) ;
deleteSnake( Ghost) ;
}
}
while ( playAgain == 1 ) ;
gotoxy( 1 , 23 ) ;
system ( "pause" ) ;
return 0 ;
}
// ham gotoxy: dua con tro toi vi tri (x, y)
void gotoxy( short x, short y)
{
HANDLE hCon = GetStdHandle( STD_OUTPUT_HANDLE) ;
COORD pos;
pos.X = x- 1 ;
pos.Y = y- 1 ;
SetConsoleCursorPosition( hCon, pos) ;
}
// tao vi tri cua 1 nut
viTri newNoc ( int x, int y) {
viTri result;
result.x = x;
result.y = y;
return result;
}
// tao nut con ran moi
void addHead ( snake * & head, int x, int y) {
snake * tmp = new snake;
( tmp- > data) .x = x;
( tmp- > data) .y = y;
if ( head == NULL ) {
head = tmp;
}
else {
tmp- > next = head;
head = tmp;
}
tmp = NULL ;
}
// chep du lieu vi tri vao nut moi cua con ran ( khi an duoc thuc an)
void addEnd ( snake * & head, int x, int y) {
snake * tmp = new snake;
snake * copy = new snake;
copy = head;
( tmp- > data) .x = x;
( tmp- > data) .y = y;
tmp- > next = NULL ;
if ( head == NULL ) {
head = tmp;
}
else {
while ( copy- > next ! = NULL )
copy = copy- > next;
copy- > next = tmp;
}
}
// do dai cua ran
int length ( snake * & head) {
int i = 0 ;
snake * q = new snake;
q = head;
while ( q ! = NULL ) {
q = q- > next;
i++ ;
}
return i;
}
// sao chep vi tri nut 2 vao nut 1
void copy ( snake * & head1, snake * & head2) {
( head1- > data) .x = ( head2- > data) .x ;
( head1- > data) .y = ( head2- > data) .y ;
}
// tao phong nen de choi game
void background ( snake * & head) {
//tao khung tuong
for ( int k = 1 ; k <= TUNG_DO; k++ ) {
gotoxy( 1 , k) ;
cout << "+" ;
}
for ( int k = 1 ; k <= HOANG_DO; k++ ) {
gotoxy( k, 1 ) ;
cout << "+" ;
}
for ( int k = 1 ; k <= TUNG_DO; k++ ) {
gotoxy( HOANG_DO, k) ;
cout << "+" ;
}
for ( int k = 1 ; k <= HOANG_DO; k++ ) {
gotoxy( k, TUNG_DO) ;
cout << "+" ;
}
gotoxy ( 62 , 3 ) ;
cout << "SNAKE GAME" ;
gotoxy( 62 , 5 ) ;
cout << "Score:" ;
gotoxy( 69 , 5 ) ;
cout << length ( head) ;
}
// thoi gian dung cua con ran, nut con control la A, W, S, D de chi huong di chuyen
void atime ( long & doKho, int & control1, int & control2) {
// cin.ignore();
int mid = control2;
for ( int j = 0 ; j < doKho; j++ ) {
if ( checkKey( VK_LEFT) || checkKey( KEY_A) )
control2 = 1 ;
if ( checkKey( VK_UP) || checkKey( KEY_W) )
control2 = 2 ;
if ( checkKey( VK_RIGHT) || checkKey( KEY_D) )
control2 = 3 ;
if ( checkKey( VK_DOWN) || checkKey( KEY_S) )
control2 = 4 ;
}
if ( control2 == ( control1 - 2 ) || control2 == ( control1 + 2 ) )
control2 = mid;
}
// di chuyen con ran = di chuyen lan luot tung nut cua con ran (*)
void movieSnake ( snake * & head, int & control1, int & control2) {
// di chuyen cac nut sau
snake * q = new snake;
q = head;
while ( q- > next ! = NULL ) {
q = q- > next;
}
( q- > data) .y = 1 ;
// copy data cua nut sau vao nut truoc
snake * k = new snake;
while ( 1 ) {
k = head;
while ( q ! = k- > next) {
k = k- > next;
}
copy( q, k) ;
q = k;
if ( q == head) break ;
k = NULL ;
}
q = NULL ;
// di chuyen nut 1, theo huong a, w, d, s
if ( control2 == 1 ) // a
( head- > data) .x - = 1 ;
if ( control2 == 2 ) // w
( head- > data) .y - = 1 ;
if ( control2 == 3 ) // d
( head- > data) .x + = 1 ;
if ( control2 == 4 ) // s
( head- > data) .y + = 1 ;
}
// in ca con ran sau khi xoa man hinh
void print ( snake * & head) {
snake * q = new snake;
q = head;
// nut 1
gotoxy ( ( q- > data) .x , ( q- > data) .y ) ;
cout << "*" ;
q = q- > next;
// cac nut sau
while ( q ! = NULL ) {
gotoxy ( ( q- > data) .x , ( q- > data) .y ) ;
cout << "+" ;
q = q- > next;
}
q = NULL ;
}
// trong time chay kiem tra co an nut di chuyen hay ko
bool checkKey( int key)
{
return GetAsyncKeyState( key) ;
}
// xoa man hinh
void xoaMH ( ) {
for ( int i = 2 ; i < TUNG_DO; i++ ) {
gotoxy ( 2 , i) ;
cout << " " ;
}
}
// dieu kien di chuyen: ko dam trung duoi, ko dam trung tuong
bool isMovie( snake * & head, snake * & ghost, int & score) {
snake * q = new snake;
q = head;
while ( q- > next ! = NULL ) {
// xem co dam trung ghost hay ko
if ( ghost ! = NULL ) {
snake * k = new snake;
k = ghost;
while ( k- > next ! = NULL ) {
if ( ( q- > data) .x == ( k- > data) .x && ( q- > data) .y == ( k- > data) .y ) {
theEnd ( head, score) ;
return 1 ;
}
k = k- > next;
}
k = NULL ;
}
q = q- > next;
if ( ( q- > data) .x == ( head- > data) .x && ( q- > data) .y == ( head- > data) .y ) {
theEnd ( head, score) ;
return 1 ;
}
}
if ( ( head- > data) .x == 1 ) {
theEnd ( head, score) ;
return 1 ;
}
if ( ( head- > data) .y == 1 ) {
theEnd ( head, score) ;
return 1 ;
}
if ( ( head- > data) .x == HOANG_DO) {
theEnd ( head, score) ;
return 1 ;
}
if ( ( head- > data) .y == TUNG_DO) {
theEnd ( head, score) ;
return 1 ;
}
return 0 ;
}
// in man hinh ket thuc game
void theEnd ( snake * & head, int & score) {
system ( "cls" ) ;
gotoxy ( 30 , 5 ) ;
cout << "GAME OVER" ;
gotoxy( 29 , 8 ) ;
cout << "Score:" ;
gotoxy( 38 , 8 ) ;
cout << score;
}
// tao thuc an moi
bool newFood ( viTri & food) {
srand ( time ( 0 ) ) ;
food.x = ( rand ( ) ) % ( HOANG_DO - 2 ) + 2 ;
food.y = ( rand ( ) ) % ( TUNG_DO - 2 ) + 2 ;
gotoxy( food.x , food.y ) ;
cout << "O" ;
return 1 ;
}
void checkEat ( snake * & head, snake * & ghost, viTri & food, int & score) {
// truong hop an duoc food
if ( ( head- > data) .x == food.x && ( head- > data) .y == food.y )
{
newFood ( food) ; // tao new food
// tao nut moi o duoi con ran
snake * q = new snake;
q = head;
while ( q- > next ! = NULL )
q = q- > next;
addEnd( head, ( q- > data) .x , ( q- > data) .y ) ;
// them diem so
gotoxy( 69 , 5 ) ;
score + = 15 ;
cout << score;
//tao ghost
int ghost_x = ( rand ( ) ) % ( HOANG_DO - 2 ) + 2 ;
addHead( ghost, ghost_x, 2 ) ;
}
else {
gotoxy( food.x , food.y ) ;
cout << "O" ;
}
}
// Chia do kho cua game, tuy theo toc do di chuyen cua con ran
void level ( long & doKho) {
int result;
do {
gotoxy ( 20 , 5 ) ;
cout << "1. Easy" ;
gotoxy ( 20 , 6 ) ;
cout << "2. Medium" ;
gotoxy ( 20 , 7 ) ;
cout << "3. Dificult" ;
gotoxy ( 14 , 9 ) ;
cout << "Please choose level (1->3): " ;
cin >> result;
}
while ( result > 3 || result < 0 ) ;
if ( result == 1 ) doKho = 8e4 ;
if ( result == 2 ) doKho = 4e4 ;
if ( result == 3 ) doKho = 2e4 ;
}
// tao chuong ngai vat di chuyen tu tren xuong, ran dam trung thi se thua
void ghost ( snake * & ghost, int & runGhost) {
if ( ghost == NULL ) return ;
//xoa ghost neu ra khoi man hinh
if ( ( ghost- > data) .y >= TUNG_DO)
ghost = ghost- > next;
snake * q = new snake;
q = ghost;
while ( q- > next ! = NULL ) {
if ( ( q- > next- > data) .y >= TUNG_DO) {
q- > next = q- > next- > next;
break ;
}
q = q- > next;
}
// cho ghost di xuong
q = ghost;
if ( runGhost% 4 == 0 ) {
while ( q- > next ! = NULL ) {
( q- > data) .y + = 1 ;
q = q- > next;
}
q = NULL ;
}
}
// in chuong ngai vat
void printGhost ( snake * & ghost) {
if ( ghost == NULL ) return ;
snake * q = new snake;
q = ghost;
while ( q- > next ! = NULL ) {
gotoxy ( ( q- > data) .x , ( q- > data) .y ) ;
cout << "*" ;
q = q- > next;
}
}
// xoa con ran sau khi game ket thuc, ham nay dang hoan thien
void deleteSnake ( snake * & head) {
delete [ ] head;
}
LyoKICoJRmlsZTogU25ha2UuY3BwCiAqCUNyZWF0b3I6IEgzU2p1bmlvcgogKgkKICoJVHJvIGNob2kgY29uIHJhbiBzYW4gbW9pCiAqLwogCiAKLy8gWSB0dW9uZzoKLy8gIC0gY29uIHJhbiBkaSBjaHV5ZW4gdHJvbmcgcGhhbiBnaW9pIGhhbiwgYW4gdGh1YyBhbiwgdHJhbmggY2FjIGNodW9uZyBuZ2FpIHZhdAovLwktIGR1bmcgZGFuaCBzYWNoIGxpZW4ga2V0Ci8vCS0gbW9pIG51dCBjdWEgZGFuaCBzYWNoIGxpZW4ga2V0IGxhIG1vdCBudXQgY3VhIGNvbiByYW46IGR1IGxpZXUgdmUgdmkgdHJpLCBjb24gdHJvIGNoaSB2ZSBudXQgcGhpYSBzYXUgY3VhIG5vCi8vCS0gY2FjaCB0aHVjIGRpIGNodXllbjogaW4gdGF0IGNhIHZpIHRyaSBjYWMgbnV0LCB0aG9pIGdpYW4gY2hvIG5ndW9pIGR1bmcgbmhhcCBodW9uZyBkaSBjaHV5ZW4sIHhvYSBtYW4gaGluaCwgaW4gdGF0IGNhIHZpIHRyaSBjYWMgbnV0IHNhdSBraGkgZGkgY2h1eWVuCgoKI2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8Y29uaW8uaD4KI2luY2x1ZGUgPHdpbmRvd3MuaD4KI2luY2x1ZGUgPGN0aW1lPgojaW5jbHVkZSA8Y3N0ZGxpYj4gCgovLyBEaW5oIG5naGlhIGNhYyBwaGltIGRpIGNodXllbiB0cmVuIGJhbiBwaGltOiBhLCBkLCB3LCBzCiNkZWZpbmUgICAgS0VZX0EgICAgMHg0MQkJCiNkZWZpbmUgICAgS0VZX0QgICAgMHg0NAojZGVmaW5lICAgIEtFWV9XICAgIDB4NTcKI2RlZmluZSAgICBLRVlfUyAgICAweDUzCgp1c2luZyBuYW1lc3BhY2Ugc3RkOwoKLy8gZHVvbmcgYmllbiBnaW9pIGhhbiBjb24gcmFuIGNvIHRoZSBkaSBjaHV5ZW4KY29uc3QgaW50IFRVTkdfRE8gPSAyMDsKY29uc3QgaW50IEhPQU5HX0RPID0gNjA7CgoKLy8gdGFvIHZpIHRyaSBtb2kKc3RydWN0IHZpVHJpIHsKCWludCB4OwoJaW50IHk7Cn07CgovLyBkYW5oIHNhY2ggbGllbiBrZXQgY2FjIG51dCBjdWEgY29uIHJhbgpzdHJ1Y3Qgc25ha2V7Cgl2aVRyaSBkYXRhOwoJc25ha2UgKiBuZXh0Owp9OwoKdm9pZCBnb3RveHkoc2hvcnQgeCwgc2hvcnQgeSk7CQkJCQkJCQkJCQkJLy8gaGFtIGdvdG94eTogZHVhIGNvbiB0cm8gdG9pIHZpIHRyaSAoeCwgeSkKdmlUcmkgbmV3Tm9jIChpbnQgeCwgaW50IHkpOwkJCQkJCQkJCQkJCS8vIHRhbyB2aSB0cmkgY3VhIDEgbnV0IAp2b2lkIGFkZEhlYWQgKHNuYWtlIComIGhlYWQsIGludCB4LCBpbnQgeSk7CQkJCQkJCQkJLy8gdGFvIG51dCBjb24gcmFuIG1vaQp2b2lkIGFkZEVuZCAoc25ha2UgKiYgaGVhZCwgaW50IHgsIGludCB5KTsJCQkJCQkJCQkvLyBjaGVwIGR1IGxpZXUgdmkgdHJpIHZhbyBudXQgbW9pIGN1YSBjb24gcmFuICgga2hpIGFuIGR1b2MgdGh1YyBhbikKaW50IGxlbmd0aCAoc25ha2UgKiYgaGVhZCk7CQkJCQkJCQkJCQkJCS8vIGRvIGRhaSBjdWEgcmFuCnZvaWQgY29weSAoc25ha2UgKiYgaGVhZDEsIHNuYWtlIComIGhlYWQyKTsJCQkJCQkJCQkvLyBzYW8gY2hlcCB2aSB0cmkgbnV0IDIgdmFvIG51dCAxCnZvaWQgYmFja2dyb3VuZCAoc25ha2UgKiYgaGVhZCk7IAkJCQkJCQkJCQkJLy8gdGFvIHBob25nIG5lbiBkZSBjaG9pIGdhbWUKdm9pZCBhdGltZSAobG9uZyAmIGRvS2hvLCBpbnQgJiBjb250cm9sMSwgaW50ICYgY29udHJvbDIpOwkJCQkJLy8gdGhvaSBnaWFuIGR1bmcgY3VhIGNvbiByYW4sIG51dCBjb24gY29udHJvbCBsYSBBLCBXLCBTLCBEIGRlIGNoaSBodW9uZyBkaSBjaHV5ZW4Kdm9pZCBtb3ZpZVNuYWtlIChzbmFrZSAqJiBoZWFkLCBpbnQgJiBjb250cm9sMSwgaW50ICYgY29udHJvbDIpCTsJCQkvLyBkaSBjaHV5ZW4gY29uIHJhbiA9IGRpIGNodXllbiBsYW4gbHVvdCB0dW5nIG51dCBjdWEgY29uIHJhbiAoKikKdm9pZCBwcmludCAoc25ha2UgKiYgaGVhZCk7CQkJCQkJCQkJCQkJCS8vIGluIGNhIGNvbiByYW4gc2F1IGtoaSB4b2EgbWFuIGhpbmgKYm9vbCBjaGVja0tleShpbnQga2V5KTsJCQkJCQkJCQkJCQkJCS8vIHRyb25nIHRpbWUgY2hheSBraWVtIHRyYSBjbyBhbiBudXQgZGkgY2h1eWVuIGhheSBrbwp2b2lkIHhvYU1IICgpOwkJCQkJCQkJCQkJCQkJCQkvLyB4b2EgbWFuIGhpbmgKYm9vbCBpc01vdmllKHNuYWtlIComIGhlYWQsIHNuYWtlIComIGdob3N0LCBpbnQgJiBzY29yZSk7CQkJCQkvLyBkaWV1IGtpZW4gZGkgY2h1eWVuOiBrbyBkYW0gdHJ1bmcgZHVvaSwga28gZGFtIHRydW5nIHR1b25nCnZvaWQgdGhlRW5kIChzbmFrZSAqJiBoZWFkLCBpbnQgJiBzY29yZSk7CQkJCQkJCQkJLy8gaW4gbWFuIGhpbmgga2V0IHRodWMgZ2FtZQpib29sIG5ld0Zvb2QgKHZpVHJpICYgZm9vZCk7CQkJCQkJCQkJCQkJLy8gdGFvIHRodWMgYW4gbW9pCnZvaWQgY2hlY2tFYXQgKHNuYWtlIComIGhlYWQsIHNuYWtlIComIGdob3N0LCB2aVRyaSAmIGZvb2QsIGludCAmIHNjb3JlKTsJLy8gS2llbSB0cmEgcmFuIGNvIGFuIGR1b2MgdGh1YyBhbiBoYXkga2hvbmcKdm9pZCBsZXZlbCAobG9uZyAmIGRvS2hvKTsJCQkJCQkJCQkJCQkJLy8gQ2hpYSBkbyBraG8gY3VhIGdhbWUsIHR1eSB0aGVvIHRvYyBkbyBkaSBjaHV5ZW4gY3VhIGNvbiByYW4Kdm9pZCBnaG9zdCAoc25ha2UgKiYgZ2hvc3QsIGludCAmIHJ1bkdob3N0KTsJCQkJCQkJCS8vIHRhbyBjaHVvbmcgbmdhaSB2YXQgZGkgY2h1eWVuIHR1IHRyZW4geHVvbmcsIHJhbiBkYW0gdHJ1bmcgdGhpIHNlIHRodWEKdm9pZCBwcmludEdob3N0IChzbmFrZSAqJiBnaG9zdCk7CQkJCQkJCQkJCQkvLyBpbiBjaHVvbmcgbmdhaSB2YXQKdm9pZCBkZWxldGVTbmFrZSAoc25ha2UgKiYgaGVhZCk7CQkJCQkJCQkJCQkvLyB4b2EgY29uIHJhbiBzYXUga2hpIGdhbWUga2V0IHRodWMsIGhhbSBuYXkgZGFuZyBob2FuIHRoaWVuCgppbnQgbWFpbiAoKQp7CglpbnQgcGxheUFnYWluID0gMDsKCWludCBjb250cm9sMSA7CQkJLy8gbGVuaCBkaWV1IGtoaWVuIHRydW9jIGRvCglpbnQgY29udHJvbDI7CQkJLy8gbGVuaCBkaWV1IGtoaWVuIHNhdQoJaW50IGkgPSAwLCBlbmQgPSAwLCBzY29yZSA9IDAsIHJ1bkdob3N0ID0gMDsKCXZpVHJpIGZvb2Q7Cglsb25nIGRvS2hvOwoJaW50IGJlc3RTY29yZSA9IDA7CQoJZG8JCgl7CQoJCXNuYWtlICpTbmFrZTsJCQkvLyBjb24gcmFuCgkJc25ha2UgKkdob3N0OwkJCS8vIGNodW9uZyBuZ2FpIHZhdAoJCVNuYWtlID0gTlVMTDsKCQlHaG9zdCA9IE5VTEw7CgkJYWRkSGVhZCAoU25ha2UsIDIsIDUpOwoJCWFkZEhlYWQgKFNuYWtlLCAzLCA1KTsKCQlhZGRIZWFkIChTbmFrZSwgNCwgNSk7CgkJYWRkSGVhZCAoU25ha2UsIDUsIDUpOwoJCWFkZEhlYWQgKFNuYWtlLCA2LCA1KTsKCQoJCWJhY2tncm91bmQgKFNuYWtlKTsJCQkvLyB0YW8ga2h1bmcgbmVuIGN1YSBjaHVvbmcgdHJpbmgKCQkKCQlzY29yZSA9IGxlbmd0aChTbmFrZSk7CgkJY29udHJvbDEgPSBjb250cm9sMiA9IDM7CgkJeG9hTUggKCk7CgkJbGV2ZWwgKGRvS2hvKTsKCQlwcmludCAoU25ha2UpOwoJCW5ld0Zvb2QgKGZvb2QpOwoJCXdoaWxlICgxKSB7CgkJCWlmIChpc01vdmllIChTbmFrZSwgR2hvc3QsIHNjb3JlKSkgewoJCQkJZ290b3h5KDEsIDIzKTsKCQkJCXN5c3RlbSAoInBhdXNlIik7CgkJCQlicmVhazsKCQkJfQoJCQkKCQkJY2hlY2tFYXQgKFNuYWtlLCBHaG9zdCwgZm9vZCwgc2NvcmUpOwoJCQlhdGltZSAoZG9LaG8sIGNvbnRyb2wxLCBjb250cm9sMik7CgkJCW1vdmllU25ha2UgKFNuYWtlLCBjb250cm9sMiwgY29udHJvbDEpOwoJCQljb250cm9sMSA9IGNvbnRyb2wyOwoJCQl4b2FNSCAoKTsgCgkJCXByaW50IChTbmFrZSk7CgkJCWdob3N0IChHaG9zdCwgcnVuR2hvc3QpOwoJCQlwcmludEdob3N0IChHaG9zdCk7CgkJCXJ1bkdob3N0Kys7CgkJfQoJCXhvYU1IICgpOyAKCQlnb3RveHkgKDIwLCA1KTsKCQljb3V0IDw8ICIxLiBQbGF5IGFnYWluIjsKCQlnb3RveHkgKDIwLCA2KTsKCQljb3V0IDw8ICIyLiBCYWNrIjsJCgkJZ290b3h5ICgxNCwgOCk7CgkJY291dCA8PCAiUGxlYXNlIGNob29zZSBudW1iZXIgKDEtPjIpOiAiOwkKCQljaW4gPj4gcGxheUFnYWluOwoJCQoJCWlmICggcGxheUFnYWluID09IDEpCXsKCQkJZGVsZXRlU25ha2UoU25ha2UpOwoJCQlkZWxldGVTbmFrZShHaG9zdCk7CgkJfQoJfQoJd2hpbGUgKCBwbGF5QWdhaW4gPT0gMSk7CgkKCWdvdG94eSgxLCAyMyk7CglzeXN0ZW0oInBhdXNlIik7CglyZXR1cm4gMDsKfQoKCgovLyBoYW0gZ290b3h5OiBkdWEgY29uIHRybyB0b2kgdmkgdHJpICh4LCB5KQp2b2lkIGdvdG94eShzaG9ydCB4LCBzaG9ydCB5KQp7CiAgICBIQU5ETEUgaENvbiA9IEdldFN0ZEhhbmRsZShTVERfT1VUUFVUX0hBTkRMRSk7CiAgICBDT09SRCBwb3M7CiAgICBwb3MuWCA9IHgtMTsKICAgIHBvcy5ZID0geS0xOwogICAgU2V0Q29uc29sZUN1cnNvclBvc2l0aW9uKGhDb24sIHBvcyk7Cn0KCi8vIHRhbyB2aSB0cmkgY3VhIDEgbnV0IAp2aVRyaSBuZXdOb2MgKGludCB4LCBpbnQgeSkgewoJdmlUcmkgcmVzdWx0OwoJcmVzdWx0LnggPSB4OwoJcmVzdWx0LnkgPSB5OwoJcmV0dXJuIHJlc3VsdDsKfQoKLy8gdGFvIG51dCBjb24gcmFuIG1vaQp2b2lkIGFkZEhlYWQgKHNuYWtlIComIGhlYWQsIGludCB4LCBpbnQgeSkJewoJc25ha2UgKnRtcCA9IG5ldyBzbmFrZTsJCQkJCQkJCQkJCQkKCSh0bXAtPmRhdGEpLnggPSB4OwoJKHRtcC0+ZGF0YSkueSA9IHk7CglpZiAoaGVhZCA9PSBOVUxMKQl7CgkJaGVhZCA9IHRtcDsKCX0KCWVsc2UgewoJCXRtcC0+bmV4dCA9IGhlYWQ7CgkJaGVhZCA9IHRtcDsKCX0KCXRtcCA9IE5VTEw7Cn0KCi8vIGNoZXAgZHUgbGlldSB2aSB0cmkgdmFvIG51dCBtb2kgY3VhIGNvbiByYW4gKCBraGkgYW4gZHVvYyB0aHVjIGFuKQp2b2lkIGFkZEVuZCAoc25ha2UgKiYgaGVhZCwgaW50IHgsIGludCB5KQl7CglzbmFrZSAqdG1wID0gbmV3IHNuYWtlOwoJc25ha2UgKmNvcHkgPSBuZXcgc25ha2U7Cgljb3B5ID0gaGVhZDsKCSh0bXAtPmRhdGEpLnggPSB4OwoJKHRtcC0+ZGF0YSkueSA9IHk7Cgl0bXAtPm5leHQgPSBOVUxMOwoJaWYgKGhlYWQgPT0gTlVMTCkJewoJCWhlYWQgPSB0bXA7Cgl9CgllbHNlCXsKCQl3aGlsZSAoY29weS0+bmV4dCAhPSBOVUxMKQkKCQkJY29weSA9IGNvcHktPm5leHQ7CgkJY29weS0+bmV4dCA9IHRtcDsJCQoJfQp9CgovLyBkbyBkYWkgY3VhIHJhbgppbnQgbGVuZ3RoIChzbmFrZSAqJiBoZWFkKQl7CglpbnQgaSA9IDA7CglzbmFrZSAqcSA9IG5ldyBzbmFrZTsKCXEgPSBoZWFkOwoJd2hpbGUgKHEgIT0gTlVMTCkJewoJCXEgPSBxLT5uZXh0OwoJCWkrKzsKCX0KCXJldHVybiBpOwp9CgovLyBzYW8gY2hlcCB2aSB0cmkgbnV0IDIgdmFvIG51dCAxCnZvaWQgY29weSAoc25ha2UgKiYgaGVhZDEsIHNuYWtlIComIGhlYWQyKQl7CgkoaGVhZDEtPmRhdGEpLnggPSAoaGVhZDItPmRhdGEpLng7CgkoaGVhZDEtPmRhdGEpLnkgPSAoaGVhZDItPmRhdGEpLnk7Cn0KCi8vIHRhbyBwaG9uZyBuZW4gZGUgY2hvaSBnYW1lCnZvaWQgYmFja2dyb3VuZCAoc25ha2UgKiYgaGVhZCkJewoJLy90YW8ga2h1bmcgdHVvbmcKCWZvciAoaW50IGsgPSAxOyBrIDw9IFRVTkdfRE87IGsrKykJewoJCWdvdG94eSgxLCBrKTsKCQljb3V0IDw8ICIrIjsKCX0KCWZvciAoaW50IGsgPSAxOyBrIDw9IEhPQU5HX0RPOyBrKyspCXsKCQlnb3RveHkoaywgMSk7CgkJY291dCA8PCAiKyI7Cgl9Cglmb3IgKGludCBrID0gMTsgayA8PSBUVU5HX0RPOyBrKyspCXsKCQlnb3RveHkoSE9BTkdfRE8sIGspOwoJCWNvdXQgPDwgIisiOwoJfQoJZm9yIChpbnQgayA9IDE7IGsgPD0gSE9BTkdfRE87IGsrKykJewoJCWdvdG94eShrLCBUVU5HX0RPKTsKCQljb3V0IDw8ICIrIjsKCX0JCgkKCWdvdG94eSAoNjIsIDMpOwoJY291dCA8PCAiU05BS0UgR0FNRSI7Cglnb3RveHkoNjIsIDUpOwoJY291dCA8PCAiU2NvcmU6IjsKCWdvdG94eSg2OSwgNSk7Cgljb3V0IDw8IGxlbmd0aCAoaGVhZCk7Cn0KCi8vIHRob2kgZ2lhbiBkdW5nIGN1YSBjb24gcmFuLCBudXQgY29uIGNvbnRyb2wgbGEgQSwgVywgUywgRCBkZSBjaGkgaHVvbmcgZGkgY2h1eWVuCnZvaWQgYXRpbWUgKGxvbmcgJiBkb0tobywgaW50ICYgY29udHJvbDEsIGludCAmIGNvbnRyb2wyKQl7Ci8vCWNpbi5pZ25vcmUoKTsgCglpbnQgbWlkID0gY29udHJvbDI7Cglmb3IgKGludCBqID0gMDsgaiA8IGRvS2hvOyBqKyspCXsKCQlpZiAoY2hlY2tLZXkoVktfTEVGVCkgfHwgY2hlY2tLZXkoS0VZX0EpKQoJCQljb250cm9sMiA9IDE7CgkJaWYgKGNoZWNrS2V5KFZLX1VQKSB8fCBjaGVja0tleShLRVlfVykpCgkJCWNvbnRyb2wyID0gMjsKCQlpZiAoY2hlY2tLZXkoVktfUklHSFQpIHx8IGNoZWNrS2V5KEtFWV9EKSkKCQkJY29udHJvbDIgPSAzOwoJCWlmIChjaGVja0tleShWS19ET1dOKSB8fCBjaGVja0tleShLRVlfUykpCgkJCWNvbnRyb2wyID0gNDsJCgl9CglpZiAoY29udHJvbDIgPT0gKGNvbnRyb2wxIC0gMikgfHwgY29udHJvbDIgPT0gKGNvbnRyb2wxICsgMikpCgkJY29udHJvbDIgPSBtaWQ7Cn0KCi8vIGRpIGNodXllbiBjb24gcmFuID0gZGkgY2h1eWVuIGxhbiBsdW90IHR1bmcgbnV0IGN1YSBjb24gcmFuICgqKQp2b2lkIG1vdmllU25ha2UgKHNuYWtlIComIGhlYWQsIGludCAmIGNvbnRyb2wxLCBpbnQgJiBjb250cm9sMikJewovLyBkaSBjaHV5ZW4gY2FjIG51dCBzYXUKCXNuYWtlICpxID0gbmV3IHNuYWtlOwoJcSA9IGhlYWQ7Cgl3aGlsZSAoIHEtPm5leHQgIT0gTlVMTCApCXsKCQlxID0gcS0+bmV4dDsKCX0KCShxLT5kYXRhKS55ID0gMTsKCQoJLy8gY29weSBkYXRhIGN1YSBudXQgc2F1IHZhbyBudXQgdHJ1b2MKCXNuYWtlICprID0gbmV3IHNuYWtlOwkKCXdoaWxlICggMSApIHsKCQlrID0gaGVhZDsKCQl3aGlsZSAocSAhPSBrLT5uZXh0KQl7CgkJCWsgPSBrLT5uZXh0OwoJCX0KCQljb3B5KHEsIGspOwoJCXEgPSBrOwoJCWlmIChxID09IGhlYWQpIGJyZWFrOwoJCWsgPSBOVUxMOwoJfQoJcSA9IE5VTEw7CgovLyBkaSBjaHV5ZW4gbnV0IDEsIHRoZW8gaHVvbmcgYSwgdywgZCwgcwoJaWYgKGNvbnRyb2wyID09IDEpCQkJLy8gYQoJCShoZWFkLT5kYXRhKS54IC09IDE7CQoJaWYgKGNvbnRyb2wyID09IDIpCQkJLy8gdwoJCShoZWFkLT5kYXRhKS55IC09IDE7CglpZiAoY29udHJvbDIgPT0gMykJCQkvLyBkCgkJKGhlYWQtPmRhdGEpLnggKz0gMTsKCWlmIChjb250cm9sMiA9PSA0KQkJCS8vIHMKCQkoaGVhZC0+ZGF0YSkueSArPSAxOwp9CgovLyBpbiBjYSBjb24gcmFuIHNhdSBraGkgeG9hIG1hbiBoaW5oCnZvaWQgcHJpbnQgKHNuYWtlIComIGhlYWQpCXsKCXNuYWtlICpxID0gbmV3IHNuYWtlOwoJcSA9IGhlYWQ7CgkKCS8vIG51dCAxCglnb3RveHkgKChxLT5kYXRhKS54LCAocS0+ZGF0YSkueSk7Cgljb3V0IDw8ICIqIjsKCXEgPSBxLT5uZXh0OwoJCQoJLy8gY2FjIG51dCBzYXUKCXdoaWxlICggcSAhPSBOVUxMKQl7CgkJZ290b3h5ICgocS0+ZGF0YSkueCwgKHEtPmRhdGEpLnkpOwoJCWNvdXQgPDwgIisiOwoJCXEgPSBxLT5uZXh0OwoJfQoJcSA9IE5VTEw7Cn0KCi8vIHRyb25nIHRpbWUgY2hheSBraWVtIHRyYSBjbyBhbiBudXQgZGkgY2h1eWVuIGhheSBrbwpib29sIGNoZWNrS2V5KGludCBrZXkpCnsKICAgIHJldHVybiBHZXRBc3luY0tleVN0YXRlKGtleSk7Cn0KCgovLyB4b2EgbWFuIGhpbmgKdm9pZCB4b2FNSCAoKQl7Cglmb3IgKGludCBpID0gMjsgaSA8IFRVTkdfRE87IGkrKykJewoJCQlnb3RveHkgKDIsIGkpOwoJCQljb3V0IDw8ICIgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjsKCQl9Cn0KCi8vIGRpZXUga2llbiBkaSBjaHV5ZW46IGtvIGRhbSB0cnVuZyBkdW9pLCBrbyBkYW0gdHJ1bmcgdHVvbmcKYm9vbCBpc01vdmllKHNuYWtlIComIGhlYWQsIHNuYWtlIComIGdob3N0LCBpbnQgJiBzY29yZSkJewoJc25ha2UgKnEgPSBuZXcgc25ha2U7CglxID0gaGVhZDsKCgl3aGlsZSAocS0+bmV4dCAhPSBOVUxMKQl7CgkJLy8geGVtIGNvIGRhbSB0cnVuZyBnaG9zdCBoYXkga28KCQlpZiAoZ2hvc3QgIT0gTlVMTCkJewoJCQlzbmFrZSAqayA9IG5ldyBzbmFrZTsKCQkJayA9IGdob3N0OwoJCQl3aGlsZSAoay0+bmV4dCAhPSBOVUxMKQl7CgkJCQlpZiAoKHEtPmRhdGEpLnggPT0gKGstPmRhdGEpLnggJiYgKHEtPmRhdGEpLnkgPT0gKGstPmRhdGEpLnkpCXsKCQkJCQl0aGVFbmQgKGhlYWQsIHNjb3JlKTsKCQkJCQlyZXR1cm4gMTsKCQkJCX0KCQkJCWsgPSBrLT5uZXh0OwoJCQl9CgkJCWsgPSBOVUxMOwoJCX0KCgkJcSA9IHEtPm5leHQ7CgkJaWYgKChxLT5kYXRhKS54ID09IChoZWFkLT5kYXRhKS54ICYmIChxLT5kYXRhKS55ID09IChoZWFkLT5kYXRhKS55KQl7CgkJCXRoZUVuZCAoaGVhZCwgc2NvcmUpOwoJCQlyZXR1cm4gMTsKCQl9CgkJCgoJfQoJCglpZiAoKGhlYWQtPmRhdGEpLnggPT0gMSkJewoJCXRoZUVuZCAoaGVhZCwgc2NvcmUpOwoJCXJldHVybiAxOwoJfQoJCQkKCWlmICgoaGVhZC0+ZGF0YSkueSA9PSAxKQl7CgkJdGhlRW5kIChoZWFkLCBzY29yZSk7CgkJcmV0dXJuIDE7Cgl9CglpZiAoKGhlYWQtPmRhdGEpLnggPT0gSE9BTkdfRE8pCXsKCQl0aGVFbmQgKGhlYWQsIHNjb3JlKTsKCQlyZXR1cm4gMTsKCX0KCQkJCglpZiAoKGhlYWQtPmRhdGEpLnkgPT0gVFVOR19ETykJewoJCXRoZUVuZCAoaGVhZCwgc2NvcmUpOwoJCXJldHVybiAxOwoJfQkKCQoJcmV0dXJuIDA7Cn0KCi8vIGluIG1hbiBoaW5oIGtldCB0aHVjIGdhbWUKdm9pZCB0aGVFbmQgKHNuYWtlIComIGhlYWQsIGludCAmIHNjb3JlKQl7CglzeXN0ZW0oImNscyIpOwoJZ290b3h5ICgzMCwgNSk7Cgljb3V0IDw8ICJHQU1FIE9WRVIiOwoJZ290b3h5KDI5LCA4KTsKCWNvdXQgPDwgIlNjb3JlOiI7Cglnb3RveHkoMzgsIDgpOwoJY291dCA8PCBzY29yZTsKfQoKLy8gdGFvIHRodWMgYW4gbW9pCmJvb2wgbmV3Rm9vZCAodmlUcmkgJiBmb29kKQl7CglzcmFuZCAodGltZSAoMCkpOwoJZm9vZC54ID0gKHJhbmQoKSklKEhPQU5HX0RPIC0gMikgKyAyOwoJZm9vZC55ID0gKHJhbmQoKSklKFRVTkdfRE8gLSAyKSArIDI7Cglnb3RveHkoZm9vZC54LCBmb29kLnkpOwoJY291dCA8PCAiTyI7CglyZXR1cm4gMTsKfQoKdm9pZCBjaGVja0VhdCAoc25ha2UgKiYgaGVhZCwgc25ha2UgKiYgZ2hvc3QsIHZpVHJpICYgZm9vZCwgaW50ICYgc2NvcmUpCXsKCS8vIHRydW9uZyBob3AgYW4gZHVvYyBmb29kCglpZiAoKGhlYWQtPmRhdGEpLnggPT0gZm9vZC54ICYmIChoZWFkLT5kYXRhKS55ID09IGZvb2QueSkJCgl7CgkJbmV3Rm9vZCAoZm9vZCk7CQkJCQkvLyB0YW8gbmV3IGZvb2QKCQkvLyB0YW8gbnV0IG1vaSBvIGR1b2kgY29uIHJhbgoJCXNuYWtlICpxID0gbmV3IHNuYWtlOwoJCXEgPSBoZWFkOwoJCXdoaWxlIChxLT5uZXh0ICE9IE5VTEwpCQoJCQlxID0gcS0+bmV4dDsKCQlhZGRFbmQoaGVhZCwgKHEtPmRhdGEpLngsIChxLT5kYXRhKS55KTsJCgkJCgkJLy8gdGhlbSBkaWVtIHNvCgkJZ290b3h5KDY5LCA1KTsKCQlzY29yZSArPSAxNTsKCQljb3V0IDw8IHNjb3JlOwoJCQoJCS8vdGFvIGdob3N0CgkJaW50IGdob3N0X3ggPSAocmFuZCgpKSUoSE9BTkdfRE8gLSAyKSArIDI7CgkJYWRkSGVhZChnaG9zdCwgZ2hvc3RfeCwgMik7Cgl9CgkKCWVsc2UgewoJCWdvdG94eShmb29kLngsIGZvb2QueSk7CgkJY291dCA8PCAiTyI7Cgl9Cn0KCi8vIENoaWEgZG8ga2hvIGN1YSBnYW1lLCB0dXkgdGhlbyB0b2MgZG8gZGkgY2h1eWVuIGN1YSBjb24gcmFuCnZvaWQgbGV2ZWwgKGxvbmcgJiBkb0tobykJewoJaW50IHJlc3VsdDsJCglkbyB7CgkJZ290b3h5ICgyMCwgNSk7CgkJY291dCA8PCAiMS4gRWFzeSI7CgkJZ290b3h5ICgyMCwgNik7CgkJY291dCA8PCAiMi4gTWVkaXVtIjsJCgkJZ290b3h5ICgyMCwgNyk7CgkJY291dCA8PCAiMy4gRGlmaWN1bHQiOwoJCWdvdG94eSAoMTQsIDkpOwoJCWNvdXQgPDwgIlBsZWFzZSBjaG9vc2UgbGV2ZWwgKDEtPjMpOiAiOwkKCQljaW4gPj4gcmVzdWx0OwoJfQoJd2hpbGUgKHJlc3VsdCA+IDMgfHwgcmVzdWx0IDwgMCk7CglpZiAocmVzdWx0ID09IDEpIGRvS2hvID0gOGU0OwoJaWYgKHJlc3VsdCA9PSAyKSBkb0tobyA9IDRlNDsKCWlmIChyZXN1bHQgPT0gMykgZG9LaG8gPSAyZTQ7Cn0KCi8vIHRhbyBjaHVvbmcgbmdhaSB2YXQgZGkgY2h1eWVuIHR1IHRyZW4geHVvbmcsIHJhbiBkYW0gdHJ1bmcgdGhpIHNlIHRodWEKdm9pZCBnaG9zdCAoc25ha2UgKiYgZ2hvc3QsIGludCAmIHJ1bkdob3N0KQl7CglpZiAoIGdob3N0ID09IE5VTEwpIHJldHVybjsKCS8veG9hIGdob3N0IG5ldSByYSBraG9pIG1hbiBoaW5oCglpZiAoKGdob3N0LT5kYXRhKS55ID49IFRVTkdfRE8pIAoJCWdob3N0ID0gZ2hvc3QtPm5leHQ7CgkJCglzbmFrZSAqcSA9IG5ldyBzbmFrZTsKCXEgPSBnaG9zdDsKCXdoaWxlICggcS0+bmV4dCAhPSBOVUxMICkJewoJCWlmICgocS0+bmV4dC0+ZGF0YSkueSA+PSBUVU5HX0RPKQl7CgkJCXEtPm5leHQgPSBxLT5uZXh0LT5uZXh0OwoJCQlicmVhazsKCQl9CgkJcSA9IHEtPm5leHQ7Cgl9CgkKCS8vIGNobyBnaG9zdCBkaSB4dW9uZwoJcSA9IGdob3N0OwoJCglpZiAocnVuR2hvc3QlNCA9PSAwKSB7CgkJd2hpbGUgKCBxLT5uZXh0ICE9IE5VTEwgKQl7CgkJCShxLT5kYXRhKS55ICs9IDE7CgkJCXEgPSBxLT5uZXh0OwoJCX0KCQlxID0gTlVMTDsKCX0KfQoKLy8gaW4gY2h1b25nIG5nYWkgdmF0CnZvaWQgcHJpbnRHaG9zdCAoc25ha2UgKiYgZ2hvc3QpCXsKCWlmICggZ2hvc3QgPT0gTlVMTCkgcmV0dXJuOwoJc25ha2UgKnEgPSBuZXcgc25ha2U7CglxID0gZ2hvc3Q7Cgl3aGlsZSAoIHEtPm5leHQgIT0gTlVMTCApCXsKCQlnb3RveHkgKChxLT5kYXRhKS54LCAocS0+ZGF0YSkueSk7CgkJY291dCA8PCAiKiI7CgkJcSA9IHEtPm5leHQ7Cgl9Cn0KCi8vIHhvYSBjb24gcmFuIHNhdSBraGkgZ2FtZSBrZXQgdGh1YywgaGFtIG5heSBkYW5nIGhvYW4gdGhpZW4Kdm9pZCBkZWxldGVTbmFrZSAoc25ha2UgKiYgaGVhZCkJewoJZGVsZXRlIFtdIGhlYWQ7Cn0=