/* ===================================================================
* by migf1
*
* Simple Guessing Game ( comments in Greek )
* - bilingual (English, Greek)
* - 2 levels of difficulty (easy, hard)
* - player defined number of tries (MINTRIES to MAXTRIES)
*
* Απλό Παιχνίδι Εύρεσης Κρυφού Αριθμού
* - δίγλωσσο (Αγγλικά, Ελληνικά)
* - 2 επίπεδα δυσκολίας (εύκολο, δύσκολο)
* - ο παίκτης επιλέγει πλήθος προσπαθειών (από MINTRIES έως MAXTRIES)
*
* Στο εύκολο επίπεδο ο κρυφός αριθμός επιλέγεται από το 1 έως το
* γινόμενο του πλήθους προσπαθειών επί LVL_EASY_MULTI, ενώ στο
* δύσκολο επίπεδο επί LVL_HARD_MULTI (ορισμένα ως 2 και 40, αντίστοιχα).
*
* Επίσης, στο δύσκολο επίπεδο το πρόγραμμα δίνει 3 ειδών απαντήσεις
* για κάθε μαντεψιά του πάικτη: "πιο ψηλά", "πιο χαμηλά" και "το
* βρήκατε". Στο εύκολο επίπεδο δίνει 4 επιπλέον απαντήσεις:
* "πιο ψηλά (είστε πολύ κοντα)", "πιο ψηλά (είστε πολύ μακριά)",
* "πιο χαμηλά (είστε πολύ κοντα)" και "πιο χαμηλά (είστε πολύ μακριά)",
* ανάλογα αν η μαντεψιά του απέχει λιγότερο από DIFF_HOT από το κρυφό νούμερο
* ή αν απέχει περισσότερο από DIFF_COLD (ορισμένα ως 2 και 10, αντίστοιχα).
* ===================================================================
*/
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
// -------- Macros ------------
#define ABS(x) ( (x) > 0 ? (x) : -(x) )
#define MAXINBUF (255+1) // μέγιστο μήκος γραμμής εισόδου
#define MINTRIES 3 // ελάχιστο πλήθος προσπαθειών
#define MAXTRIES 8 // μέγιστο πλήθος προσπαθειών
#define LVL_EASY_ID 1 // ταυτότητα εύκολου επιπέδου
#define LVL_EASY_MULTI 3 // πολλαπλ/στής εύκολου επιπέδου
#define LVL_HARD_ID 2 // ταυτότητα δύσκολου επιπέδου
#define LVL_HARD_MULTI 40 // πολλαπλ/στής δύσκολου επιπέδου
#define DIFF_HOT 2 // HOT απόσταση από κρυμμένο
#define DIFF_COLD 10 // COLD απόσταση από κρυμμένο
#define MAX_MESSAGES 15 // μέγιστο πλήθος μηνυμάτων
// ------- Πρόσθετοι Τύποι -----------
typedef enum { // θέσεις στον πίνακα μηνυμάτων
TXT_OUTOFBOUNDS = 0,
TXT_HIGHER,
TXT_HIGHERHOT,
TXT_HIGHERCOLD,
TXT_LOWER,
TXT_LOWERHOT,
TXT_LOWERCOLD,
TXT_CONGRATS,
TXT_FMT_TRIES,
TXT_UPPERLIMIT,
TXT_FMT_SETHIDDEN,
TXT_FMT_PROMPT,
TXT_FMT_MAXTRIES,
TXT_LEVEL,
TXT_FMT_LOST
} MsgPos;
typedef enum { LNG_EN=1, LNG_GR } LangCode; // κωδικοί γλωσσσών
typedef struct level { // δομή επιπέδου δυσκολίας
int id, multi; // ταυτότητα & πολλαπλασιαστής
} Level;
// -------- Πρότυπα Συναρτήσεων --------------
const char **get_language( const char **msg_en, const char **msg_gr );
void get_level( Level *level, const char *fmttext );
void get_ntries( int *ntries, const char *fmttext );
MsgPos hint_getpos(const int guess, const int hidden, const int lim, const int levid);
// ----------------------------------------------------------------------------
int main( void )
{
char inbuf[ MAXINBUF ] = ""; // η γραμμή εισόδου
int ntries, limit, guess = -1, hidden, count = 0;
MsgPos pos; // θέση κατάλληλης απάντησης
Level level = { LVL_EASY_ID, LVL_EASY_MULTI }; // επίπεδο δυσκολίας
const char **messages = NULL; // ενεργός πίνακας μηνυμάτων
const char *msg_en[MAX_MESSAGES] = { // αγγλικός πίνακας μηνυμάτων
"\tout of bounds, try again\n", // TXT_OUTOFBOUNDS
"\thigher\n", // TXT_HIGHER
"\thigher (you're too close)\n", // TXT_HIGHERHOT
"\thigher (you're far away)\n", // TXT_HIGHERCOLD
"\tlower\n", // TXT_LOWER
"\tlower (you're too close)\n", // TXT_LOWERHOT
"\tlower (you're far away)\n", // TXT_LOWERCOLD
"\nCongratulations, you found it!", // TXT_CONGRATS
"\tit took you %d tries\n\n", // TXT_FMT_TRIES
"Give upper limit ( greater than 1 ): ", // TXT_UPPERLIMIT
"\tI set a number from 1 to %d\n\n", // TXT_FMT_SETHIDDEN
"Guess #%d/%d: ", // TXT_FMT_PROMPT
"\nHow many tries (%d - %d)? ", // TXT_FMT_MAXTRIES
"\nSelect level (%d = easy, %d = hard): ", // TXT_LEVEL
"You loose, the number was: %d\n" // TXT_FMT_LOST
};
const char *msg_gr[MAX_MESSAGES] = { // ελληνικός πίνακας μηνυμάτων
"\tεκτός ορίων, ξαναπροσπαθήστε\n", // TXT_OUTOFBOUNDS
"\tπιο ψηλά\n", // TXT_HIGHER
"\tπιο ψηλά (είστε πολύ κοντά)\n", // TXT_HIGHERHOT
"\tπιο ψηλά (είστε πολύ μακριά)\n", // TXT_HIGHERCOLD
"\tπιο χαμηλά\n", // TXT_LOWER
"\tπιο χαμηλά (είστε πολύ κοντά)\n", // TXT_LOWERHOT
"\tπιο χαμηλά (είστε πολύ μακριά)\n", // TXT_LOWERCOLD
"\nΣυγχαρητήρια, το βρήκατε!", // TXT_CONGRATS
"\tχρειαστήκατε %d προσπάθειες\n\n", // TXT_FMT_TRIES
"Ανώτατο όριο ( μεγαλύτερο του 1 ): ", // TXT_UPPERLIMIT
"\tέβαλα έναν αριθμό από το 1 έως το %d\n\n", // TXT_FMT_SETHIDDEN
"Μαντεψιά #%d/%d: ", // TXT_FMT_PROMPT
"\nΠόσες προσπάθειες (%d - %d); ", // TXT_FMT_MAXTRIES
"\nΕπίπεδο δυσκολίας (%d = εύκολο, %d = δύσκολο); ",// TXT_LEVEL
"Χάσατε, το νούμερο ήταν: %d\n" // TXT_FMT_LOST
};
srand( time(NULL
) ); // γεννήτρια ψευδοτυχαίων
messages = get_language( msg_en, msg_gr ); // διάβασμα γλώσσας
get_level( &level, messages[TXT_LEVEL] ); // διάβσαμα επιπέδου δυσκολίας
get_ntries(&ntries,messages[TXT_FMT_MAXTRIES]); // διάβασμα πλήθους προσπαθειών
limit = ntries * level.multi; // καθορισμός ανώτατου ορίου
hidden
= rand() % limit
+ 1; // επιλογή τυχαίου αριθμού printf( messages
[ TXT_FMT_SETHIDDEN
], limit
);
// το κεντρικό μας loop
do {
printf( messages
[ TXT_FMT_PROMPT
], count
+1, ntries
); fgets(inbuf
, MAXINBUF
, stdin
); // διάβασμα μαντεψιάς guess
= atoi( inbuf
); // μετατροπή της σε int
pos = hint_getpos(guess,hidden,limit,level.id);// επιλογή απάντησης
if ( pos != TXT_OUTOFBOUNDS ) // έγκυρη μαντεψιά
count++; // μετρητής προσπαθειών
puts( messages
[ pos
] ); // τύπωμα απάντησης
} while ( count < ntries && guess != hidden);
if ( guess == hidden )
printf(messages
[TXT_FMT_TRIES
], count
); // τύπωμα προσπαθειών else
printf(messages
[TXT_FMT_LOST
],hidden
); // αποκάλυψη αριθμού
}
// ----------------------------------------------------------------------------
const char **get_language( const char **msg_en, const char **msg_gr )
{
char inbuf[ MAXINBUF ];
LangCode dummy;
puts("Choose language / Επιλέξτε γλώσσα:"); printf("\n\t%d: English\n\t%d: Ελληνικά\n", LNG_EN
, LNG_GR
); do {
fgets(inbuf
, MAXINBUF
, stdin
); } while (dummy < LNG_EN || dummy > LNG_GR );
if ( dummy == LNG_GR )
return msg_gr;
return msg_en;
}
// ----------------------------------------------------------------------------
void get_level( Level *level, const char *fmttext )
{
char inbuf[ MAXINBUF ];
int dummy;
do {
printf( fmttext
, LVL_EASY_ID
, LVL_HARD_ID
); fgets(inbuf
, MAXINBUF
, stdin
); } while (dummy < LVL_EASY_ID || dummy > LVL_HARD_ID);
if ( dummy == LVL_EASY_ID ) {
level->id = LVL_EASY_ID;
level->multi = LVL_EASY_MULTI;
}
else {
level->id = LVL_HARD_ID;
level->multi = LVL_HARD_MULTI;
}
return;
}
// ----------------------------------------------------------------------------
void get_ntries( int *ntries, const char *fmttext )
{
char inbuf[ MAXINBUF ];
do {
printf( fmttext
, MINTRIES
, MAXTRIES
); fgets(inbuf
, MAXINBUF
, stdin
); } while ( *ntries < MINTRIES || *ntries > MAXTRIES);
return;
}
// ----------------------------------------------------------------------------
MsgPos hint_getpos(const int guess, const int hidden, const int lim, const int levid)
{
int diff;
if (guess > lim || guess < 1)
return TXT_OUTOFBOUNDS;
if (guess == hidden )
return TXT_CONGRATS;
if ( levid == LVL_HARD_ID)
return (guess < hidden) ? TXT_HIGHER : TXT_LOWER;
diff = ABS(hidden-guess);
if (guess < hidden)
{
if ( diff <= DIFF_HOT )
return TXT_HIGHERHOT;
if ( diff > DIFF_COLD )
return TXT_HIGHERCOLD;
return TXT_HIGHER;
}
if (guess > hidden)
{
if ( diff <= DIFF_HOT )
return TXT_LOWERHOT;
if ( diff > DIFF_COLD )
return TXT_LOWERCOLD;
return TXT_LOWER;
}
return TXT_CONGRATS;
}
LyogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQogKiBieSBtaWdmMQogKgogKiBTaW1wbGUgR3Vlc3NpbmcgR2FtZSAoIGNvbW1lbnRzIGluIEdyZWVrICkKICogLQliaWxpbmd1YWwgKEVuZ2xpc2gsIEdyZWVrKQogKiAtCTIgbGV2ZWxzIG9mIGRpZmZpY3VsdHkgKGVhc3ksIGhhcmQpCiAqIC0JcGxheWVyIGRlZmluZWQgbnVtYmVyIG9mIHRyaWVzIChNSU5UUklFUyB0byBNQVhUUklFUykKICoKICogzpHPgM67z4wgzqDOsc65z4fOvc6vzrTOuSDOlc+Nz4HOtc+DzrfPgiDOms+Bz4XPhs6/z40gzpHPgc65zrjOvM6/z40KICogLQnOtM6vzrPOu8+Jz4PPg86/ICjOkc6zzrPOu865zrrOrCwgzpXOu867zrfOvc65zrrOrCkKICogLQkyIM61z4DOr8+AzrXOtM6xIM60z4XPg866zr/Ou86vzrHPgiAozrXPjc66zr/Ou86/LCDOtM+Nz4POus6/zrvOvykKICogLQnOvyDPgM6xzq/Ous+EzrfPgiDOtc+AzrnOu86tzrPOtc65IM+AzrvOrs64zr/PgiDPgM+Bzr/Pg8+AzrHOuM61zrnPjs69ICjOsc+Az4wgTUlOVFJJRVMgzq3Pic+CIE1BWFRSSUVTKQogKgogKiAJzqPPhM6/IM61z43Ous6/zrvOvyDOtc+Azq/PgM61zrTOvyDOvyDOus+Bz4XPhs+Mz4IgzrHPgc65zrjOvM+Mz4IgzrXPgM65zrvOrc6zzrXPhM6xzrkgzrHPgM+MIM+Ezr8gMSDOrc+Jz4Igz4TOvwogKgnOs865zr3PjM68zrXOvc6/IM+Ezr/PhSDPgM67zq7OuM6/z4XPgiDPgM+Bzr/Pg8+AzrHOuM61zrnPjs69IM61z4DOryBMVkxfRUFTWV9NVUxUSSwgzrXOvc+OIM+Dz4TOvwogKgnOtM+Nz4POus6/zrvOvyDOtc+Azq/PgM61zrTOvyDOtc+Azq8gTFZMX0hBUkRfTVVMVEkgKM6/z4HOuc+DzrzOrc69zrEgz4nPgiAyIM66zrHOuSA0MCwgzrHOvc+Ezq/Pg8+Ezr/Ouc+HzrEpLgogKgogKgnOlc+Azq/Pg863z4IsIM+Dz4TOvyDOtM+Nz4POus6/zrvOvyDOtc+Azq/PgM61zrTOvyDPhM6/IM+Az4HPjM6zz4HOsc68zrzOsSDOtM6vzr3Otc65IDMgzrXOuc60z47OvSDOsc+AzrHOvc+Ezq7Pg861zrnPggogKgnOs865zrEgzrrOrM64zrUgzrzOsc69z4TOtc+IzrnOrCDPhM6/z4Ugz4DOrM65zrrPhM63OiAiz4DOuc6/IM+IzrfOu86sIiwgIs+AzrnOvyDPh86xzrzOt867zqwiIM66zrHOuSAiz4TOvwogKgnOss+Bzq7Ous6xz4TOtSIuIM6jz4TOvyDOtc+NzrrOv867zr8gzrXPgM6vz4DOtc60zr8gzrTOr869zrXOuSA0IM61z4DOuc+AzrvOrc6/zr0gzrHPgM6xzr3PhM6uz4POtc65z4I6CiAqCSLPgM65zr8gz4jOt867zqwgKM61zq/Pg8+EzrUgz4DOv867z40gzrrOv869z4TOsSkiLCAiz4DOuc6/IM+IzrfOu86sICjOtc6vz4PPhM61IM+Azr/Ou8+NIM68zrHOus+BzrnOrCkiLAogKgkiz4DOuc6/IM+HzrHOvM63zrvOrCAozrXOr8+Dz4TOtSDPgM6/zrvPjSDOus6/zr3PhM6xKSIgzrrOsc65ICLPgM65zr8gz4fOsc68zrfOu86sICjOtc6vz4PPhM61IM+Azr/Ou8+NIM68zrHOus+BzrnOrCkiLAogKgnOsc69zqzOu86/zrPOsSDOsc69IM63IM68zrHOvc+EzrXPiM65zqwgz4TOv8+FIM6xz4DOrc+HzrXOuSDOu865zrPPjM+EzrXPgc6/IM6xz4DPjCBESUZGX0hPVCDOsc+Az4wgz4TOvyDOus+Bz4XPhs+MIM69zr/Pjc68zrXPgc6/CiAqCc6uIM6xzr0gzrHPgM6tz4fOtc65IM+AzrXPgc65z4PPg8+Mz4TOtc+Bzr8gzrHPgM+MIERJRkZfQ09MRCAozr/Pgc65z4POvM6tzr3OsSDPic+CIDIgzrrOsc65IDEwLCDOsc69z4TOr8+Dz4TOv865z4fOsSkuCiAqID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KICovCgojaW5jbHVkZSA8c3RkaW8uaD4KI2luY2x1ZGUgPHRpbWUuaD4KI2luY2x1ZGUgPHN0ZGxpYi5oPgoKLy8gLS0tLS0tLS0gTWFjcm9zIC0tLS0tLS0tLS0tLQoKI2RlZmluZSBBQlMoeCkJCQkoICh4KSA+IDAgPyAoeCkgOiAtKHgpICkKCiNkZWZpbmUgTUFYSU5CVUYJCSgyNTUrMSkJCQkvLyDOvM6tzrPOuc+Dz4TOvyDOvM6uzrrOv8+CIM6zz4HOsc68zrzOrs+CIM61zrnPg8+MzrTOv8+FCiNkZWZpbmUgTUlOVFJJRVMJCTMJCQkvLyDOtc67zqzPh865z4PPhM6/IM+AzrvOrs64zr/PgiDPgM+Bzr/Pg8+AzrHOuM61zrnPjs69CiNkZWZpbmUgTUFYVFJJRVMJCTgJCQkvLyDOvM6tzrPOuc+Dz4TOvyDPgM67zq7OuM6/z4Igz4DPgc6/z4PPgM6xzrjOtc65z47OvQoKI2RlZmluZSBMVkxfRUFTWV9JRAkJMQkJCS8vIM+EzrHPhc+Ez4zPhM63z4TOsSDOtc+NzrrOv867zr/PhSDOtc+AzrnPgM6tzrTOv8+FCiNkZWZpbmUgTFZMX0VBU1lfTVVMVEkJCTMJCQkvLyDPgM6/zrvOu86xz4DOuy/Pg8+Ezq7PgiDOtc+NzrrOv867zr/PhSDOtc+AzrnPgM6tzrTOv8+FCiNkZWZpbmUgTFZMX0hBUkRfSUQJCTIJCQkvLyDPhM6xz4XPhM+Mz4TOt8+EzrEgzrTPjc+DzrrOv867zr/PhSDOtc+AzrnPgM6tzrTOv8+FCiNkZWZpbmUgTFZMX0hBUkRfTVVMVEkJCTQwCQkJLy8gz4DOv867zrvOsc+Azrsvz4PPhM6uz4IgzrTPjc+DzrrOv867zr/PhSDOtc+AzrnPgM6tzrTOv8+FCgojZGVmaW5lIERJRkZfSE9UCQkyCQkJLy8gSE9UIM6xz4DPjM+Dz4TOsc+DzrcgzrHPgM+MIM66z4HPhc68zrzOrc69zr8KI2RlZmluZSBESUZGX0NPTEQJCTEwCQkJLy8gQ09MRCDOsc+Az4zPg8+EzrHPg863IM6xz4DPjCDOus+Bz4XOvM68zq3Ovc6/CgojZGVmaW5lIE1BWF9NRVNTQUdFUwkJMTUJCQkvLyDOvM6tzrPOuc+Dz4TOvyDPgM67zq7OuM6/z4IgzrzOt869z4XOvM6sz4TPic69CgovLyAtLS0tLS0tIM6gz4HPjM+DzrjOtc+Ezr/OuSDOpM+Nz4DOv865IC0tLS0tLS0tLS0tCgp0eXBlZGVmIGVudW0gewkJCQkJCS8vIM64zq3Pg861zrnPgiDPg8+Ezr/OvSDPgM6vzr3Osc66zrEgzrzOt869z4XOvM6sz4TPic69CglUWFRfT1VUT0ZCT1VORFMgPSAwLAoJVFhUX0hJR0hFUiwKCVRYVF9ISUdIRVJIT1QsCglUWFRfSElHSEVSQ09MRCwKCVRYVF9MT1dFUiwKCVRYVF9MT1dFUkhPVCwKCVRYVF9MT1dFUkNPTEQsCglUWFRfQ09OR1JBVFMsCglUWFRfRk1UX1RSSUVTLAoJVFhUX1VQUEVSTElNSVQsCglUWFRfRk1UX1NFVEhJRERFTiwKCVRYVF9GTVRfUFJPTVBULAoJVFhUX0ZNVF9NQVhUUklFUywKCVRYVF9MRVZFTCwKCVRYVF9GTVRfTE9TVAp9IE1zZ1BvczsKCnR5cGVkZWYgZW51bSB7IExOR19FTj0xLCBMTkdfR1IgfSBMYW5nQ29kZTsJCS8vIM66z4nOtM65zrrOv86vIM6zzrvPic+Dz4PPg8+Ozr0KCnR5cGVkZWYgc3RydWN0IGxldmVsIHsJCQkJCS8vIM60zr/OvM6uIM61z4DOuc+Azq3OtM6/z4UgzrTPhc+DzrrOv867zq/Osc+CCglpbnQgaWQsIG11bHRpOwkJCQkJLy8gz4TOsc+Fz4TPjM+EzrfPhM6xICYgz4DOv867zrvOsc+AzrvOsc+DzrnOsc+Dz4TOrs+CCn0gTGV2ZWw7CgovLyAtLS0tLS0tLSDOoM+Bz4zPhM+Fz4DOsSDOo8+Fzr3Osc+Bz4TOrs+DzrXPic69IC0tLS0tLS0tLS0tLS0tCgpjb25zdCBjaGFyICoqZ2V0X2xhbmd1YWdlKCBjb25zdCBjaGFyICoqbXNnX2VuLCBjb25zdCBjaGFyICoqbXNnX2dyICk7CnZvaWQgZ2V0X2xldmVsKCBMZXZlbCAqbGV2ZWwsIGNvbnN0IGNoYXIgKmZtdHRleHQgKTsKdm9pZCBnZXRfbnRyaWVzKCBpbnQgKm50cmllcywgY29uc3QgY2hhciAqZm10dGV4dCApOwpNc2dQb3MgaGludF9nZXRwb3MoY29uc3QgaW50IGd1ZXNzLCBjb25zdCBpbnQgaGlkZGVuLCBjb25zdCBpbnQgbGltLCBjb25zdCBpbnQgbGV2aWQpOwoKLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQppbnQgbWFpbiggdm9pZCApCnsKCWNoYXIgaW5idWZbIE1BWElOQlVGIF0gPSAiIjsJCQkvLyDOtyDOs8+BzrHOvM68zq4gzrXOuc+Dz4zOtM6/z4UKCWludCBudHJpZXMsIGxpbWl0LCBndWVzcyA9IC0xLCBoaWRkZW4sIGNvdW50ID0gMDsKCU1zZ1BvcyBwb3M7CQkJCQkvLyDOuM6tz4POtyDOus6xz4TOrM67zrvOt867zrfPgiDOsc+AzqzOvc+EzrfPg863z4IKCUxldmVsIGxldmVsID0geyBMVkxfRUFTWV9JRCwgTFZMX0VBU1lfTVVMVEkgfTsJLy8gzrXPgM6vz4DOtc60zr8gzrTPhc+DzrrOv867zq/Osc+CCgoJY29uc3QgY2hhciAqKm1lc3NhZ2VzID0gTlVMTDsJCQkvLyDOtc69zrXPgc6zz4zPgiDPgM6vzr3Osc66zrHPgiDOvM63zr3Phc68zqzPhM+Jzr0KCgljb25zdCBjaGFyICptc2dfZW5bTUFYX01FU1NBR0VTXSA9IHsJCS8vIM6xzrPOs867zrnOus+Mz4Igz4DOr869zrHOus6xz4IgzrzOt869z4XOvM6sz4TPic69CgkJIlx0b3V0IG9mIGJvdW5kcywgdHJ5IGFnYWluXG4iLAkJCS8vIFRYVF9PVVRPRkJPVU5EUwoJCSJcdGhpZ2hlclxuIiwJCQkJCS8vIFRYVF9ISUdIRVIKCQkiXHRoaWdoZXIgKHlvdSdyZSB0b28gY2xvc2UpXG4iLAkJLy8gVFhUX0hJR0hFUkhPVAoJCSJcdGhpZ2hlciAoeW91J3JlIGZhciBhd2F5KVxuIiwJCQkvLyBUWFRfSElHSEVSQ09MRAoJCSJcdGxvd2VyXG4iLAkJCQkJLy8gVFhUX0xPV0VSCgkJIlx0bG93ZXIgKHlvdSdyZSB0b28gY2xvc2UpXG4iLAkJCS8vIFRYVF9MT1dFUkhPVAoJCSJcdGxvd2VyICh5b3UncmUgZmFyIGF3YXkpXG4iLAkJCS8vIFRYVF9MT1dFUkNPTEQKCQkiXG5Db25ncmF0dWxhdGlvbnMsIHlvdSBmb3VuZCBpdCEiLAkJLy8gVFhUX0NPTkdSQVRTCgkJIlx0aXQgdG9vayB5b3UgJWQgdHJpZXNcblxuIiwJCQkvLyBUWFRfRk1UX1RSSUVTCgkJIkdpdmUgdXBwZXIgbGltaXQgKCBncmVhdGVyIHRoYW4gMSApOiAiLAkvLyBUWFRfVVBQRVJMSU1JVAoJCSJcdEkgc2V0IGEgbnVtYmVyIGZyb20gMSB0byAlZFxuXG4iLAkJLy8gVFhUX0ZNVF9TRVRISURERU4KCQkiR3Vlc3MgIyVkLyVkOiAiLAkJCQkvLyBUWFRfRk1UX1BST01QVCAKCQkiXG5Ib3cgbWFueSB0cmllcyAoJWQgLSAlZCk/ICIsCQkJLy8gVFhUX0ZNVF9NQVhUUklFUwoJCSJcblNlbGVjdCBsZXZlbCAoJWQgPSBlYXN5LCAlZCA9IGhhcmQpOiAiLAkvLyBUWFRfTEVWRUwKCQkiWW91IGxvb3NlLCB0aGUgbnVtYmVyIHdhczogJWRcbiIJCS8vIFRYVF9GTVRfTE9TVAoJfTsKCgljb25zdCBjaGFyICptc2dfZ3JbTUFYX01FU1NBR0VTXSA9IHsJCS8vIM61zrvOu863zr3Ouc66z4zPgiDPgM6vzr3Osc66zrHPgiDOvM63zr3Phc68zqzPhM+Jzr0KCQkiXHTOtc66z4TPjM+CIM6/z4HOr8+Jzr0sIM6+zrHOvc6xz4DPgc6/z4PPgM6xzrjOrs+Dz4TOtVxuIiwJCS8vIFRYVF9PVVRPRkJPVU5EUwoJCSJcdM+AzrnOvyDPiM63zrvOrFxuIiwJCQkJCS8vIFRYVF9ISUdIRVIKCQkiXHTPgM65zr8gz4jOt867zqwgKM61zq/Pg8+EzrUgz4DOv867z40gzrrOv869z4TOrClcbiIsCQkvLyBUWFRfSElHSEVSSE9UCgkJIlx0z4DOuc6/IM+IzrfOu86sICjOtc6vz4PPhM61IM+Azr/Ou8+NIM68zrHOus+BzrnOrClcbiIsCQkvLyBUWFRfSElHSEVSQ09MRAoJCSJcdM+AzrnOvyDPh86xzrzOt867zqxcbiIsCQkJCS8vIFRYVF9MT1dFUgoJCSJcdM+AzrnOvyDPh86xzrzOt867zqwgKM61zq/Pg8+EzrUgz4DOv867z40gzrrOv869z4TOrClcbiIsCQkvLyBUWFRfTE9XRVJIT1QKCQkiXHTPgM65zr8gz4fOsc68zrfOu86sICjOtc6vz4PPhM61IM+Azr/Ou8+NIM68zrHOus+BzrnOrClcbiIsCQkvLyBUWFRfTE9XRVJDT0xECgkJIlxuzqPPhc6zz4fOsc+BzrfPhM6uz4HOuc6xLCDPhM6/IM6yz4HOrs66zrHPhM61ISIsCQkJLy8gVFhUX0NPTkdSQVRTCgkJIlx0z4fPgc61zrnOsc+Dz4TOrs66zrHPhM61ICVkIM+Az4HOv8+Dz4DOrM64zrXOuc61z4JcblxuIiwJCS8vIFRYVF9GTVRfVFJJRVMKCQkizpHOvc+Oz4TOsc+Ezr8gz4zPgc65zr8gKCDOvM61zrPOsc67z43PhM61z4HOvyDPhM6/z4UgMSApOiAiLAkJLy8gVFhUX1VQUEVSTElNSVQKCQkiXHTOrc6yzrHOu86xIM6tzr3Osc69IM6xz4HOuc64zrzPjCDOsc+Az4wgz4TOvyAxIM6tz4nPgiDPhM6/ICVkXG5cbiIsCS8vIFRYVF9GTVRfU0VUSElEREVOCgkJIs6czrHOvc+EzrXPiM65zqwgIyVkLyVkOiAiLAkJCQkvLyBUWFRfRk1UX1BST01QVCAKCQkiXG7OoM+Mz4POtc+CIM+Az4HOv8+Dz4DOrM64zrXOuc61z4IgKCVkIC0gJWQpOyAiLAkJLy8gVFhUX0ZNVF9NQVhUUklFUwoJCSJcbs6Vz4DOr8+AzrXOtM6/IM60z4XPg866zr/Ou86vzrHPgiAoJWQgPSDOtc+NzrrOv867zr8sICVkID0gzrTPjc+DzrrOv867zr8pOyAiLC8vIFRYVF9MRVZFTAoJCSLOp86sz4POsc+EzrUsIM+Ezr8gzr3Ov8+NzrzOtc+Bzr8gzq7PhM6xzr06ICVkXG4iCQkJLy8gVFhUX0ZNVF9MT1NUCgl9OwoKCXNyYW5kKCB0aW1lKE5VTEwpICk7CQkJCS8vIM6zzrXOvc69zq7PhM+BzrnOsSDPiM61z4XOtM6/z4TPhc+HzrHOr8+Jzr0KCgltZXNzYWdlcyA9IGdldF9sYW5ndWFnZSggbXNnX2VuLCBtc2dfZ3IgKTsJLy8gzrTOuc6szrLOsc+DzrzOsSDOs867z47Pg8+DzrHPggoJZ2V0X2xldmVsKCAmbGV2ZWwsIG1lc3NhZ2VzW1RYVF9MRVZFTF0gKTsJLy8gzrTOuc6szrLPg86xzrzOsSDOtc+AzrnPgM6tzrTOv8+FIM60z4XPg866zr/Ou86vzrHPggoJZ2V0X250cmllcygmbnRyaWVzLG1lc3NhZ2VzW1RYVF9GTVRfTUFYVFJJRVNdKTsJLy8gzrTOuc6szrLOsc+DzrzOsSDPgM67zq7OuM6/z4XPgiDPgM+Bzr/Pg8+AzrHOuM61zrnPjs69CgoJbGltaXQgPSBudHJpZXMgKiBsZXZlbC5tdWx0aTsJCQkvLyDOus6xzrjOv8+BzrnPg868z4zPgiDOsc69z47PhM6xz4TOv8+FIM6/z4HOr86/z4UKCWhpZGRlbiA9IHJhbmQoKSAlIGxpbWl0ICsgMTsJCQkvLyDOtc+AzrnOu86/zrPOriDPhM+Fz4fOsc6vzr/PhSDOsc+BzrnOuM68zr/PjQoJcHJpbnRmKCBtZXNzYWdlc1sgVFhUX0ZNVF9TRVRISURERU4gXSwgbGltaXQpOwoKCS8vIM+Ezr8gzrrOtc69z4TPgc65zrrPjCDOvM6xz4IgbG9vcAoJZG8gewoJCXByaW50ZiggbWVzc2FnZXNbIFRYVF9GTVRfUFJPTVBUIF0sIGNvdW50KzEsIG50cmllcyk7CgkJZmdldHMoaW5idWYsIE1BWElOQlVGLCBzdGRpbik7CQkvLyDOtM65zqzOss6xz4POvM6xIM68zrHOvc+EzrXPiM65zqzPggoJCWd1ZXNzID0gYXRvaSggaW5idWYgKTsJCQkvLyDOvM61z4TOsc+Ez4HOv8+Azq4gz4TOt8+CIM+DzrUgaW50CgoJCXBvcyA9IGhpbnRfZ2V0cG9zKGd1ZXNzLGhpZGRlbixsaW1pdCxsZXZlbC5pZCk7Ly8gzrXPgM65zrvOv86zzq4gzrHPgM6szr3PhM63z4POt8+CCgkJaWYgKCBwb3MgIT0gVFhUX09VVE9GQk9VTkRTICkJCS8vIM6tzrPOus+Fz4HOtyDOvM6xzr3PhM61z4jOuc6sCgkJCWNvdW50Kys7CQkJLy8gzrzOtc+Ez4HOt8+Ezq7PgiDPgM+Bzr/Pg8+AzrHOuM61zrnPjs69CgkJcHV0cyggbWVzc2FnZXNbIHBvcyBdICk7CQkvLyDPhM+Nz4DPic68zrEgzrHPgM6szr3PhM63z4POt8+CCgoJfSB3aGlsZSAoIGNvdW50IDwgbnRyaWVzICYmIGd1ZXNzICE9IGhpZGRlbik7CgoJaWYgKCBndWVzcyA9PSBoaWRkZW4gKQoJCXByaW50ZihtZXNzYWdlc1tUWFRfRk1UX1RSSUVTXSwgY291bnQpOwkvLyDPhM+Nz4DPic68zrEgz4DPgc6/z4PPgM6xzrjOtc65z47OvQoJZWxzZQoJCXByaW50ZihtZXNzYWdlc1tUWFRfRk1UX0xPU1RdLGhpZGRlbik7CS8vIM6xz4DOv866zqzOu8+Fz4jOtyDOsc+BzrnOuM68zr/PjQoKCXN5c3RlbSgicGF1c2UiKTtcCglleGl0KCBFWElUX1NVQ0NFU1MgKTsKfQoKLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQpjb25zdCBjaGFyICoqZ2V0X2xhbmd1YWdlKCBjb25zdCBjaGFyICoqbXNnX2VuLCBjb25zdCBjaGFyICoqbXNnX2dyICkKewoJY2hhciBpbmJ1ZlsgTUFYSU5CVUYgXTsKCUxhbmdDb2RlIGR1bW15OwoKCXB1dHMoIkNob29zZSBsYW5ndWFnZSAvIM6Vz4DOuc67zq3Ovs+EzrUgzrPOu8+Oz4PPg86xOiIpOwoJcHJpbnRmKCJcblx0JWQ6IEVuZ2xpc2hcblx0JWQ6IM6VzrvOu863zr3Ouc66zqxcbiIsIExOR19FTiwgTE5HX0dSKTsKCWRvIHsKCQlwcmludGYoIj4gIik7CgkJZmdldHMoaW5idWYsIE1BWElOQlVGLCBzdGRpbik7CgkJZHVtbXkgPSBhdG9pKCBpbmJ1ZiApOwoJfSB3aGlsZSAoZHVtbXkgPCBMTkdfRU4gfHwgZHVtbXkgPiBMTkdfR1IgKTsKCglpZiAoIGR1bW15ID09IExOR19HUiApCgkJcmV0dXJuIG1zZ19ncjsKCglyZXR1cm4gbXNnX2VuOwp9CgovLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCnZvaWQgZ2V0X2xldmVsKCBMZXZlbCAqbGV2ZWwsIGNvbnN0IGNoYXIgKmZtdHRleHQgKQp7CgljaGFyIGluYnVmWyBNQVhJTkJVRiBdOwoJaW50IGR1bW15OwoKCWRvIHsKCQlwcmludGYoIGZtdHRleHQsIExWTF9FQVNZX0lELCBMVkxfSEFSRF9JRCApOwoJCWZnZXRzKGluYnVmLCBNQVhJTkJVRiwgc3RkaW4pOwoJCWR1bW15ID0gYXRvaSggaW5idWYgKTsKCX0gd2hpbGUgKGR1bW15IDwgTFZMX0VBU1lfSUQgfHwgZHVtbXkgPiBMVkxfSEFSRF9JRCk7CgoJaWYgKCBkdW1teSA9PSBMVkxfRUFTWV9JRCApIHsKCQlsZXZlbC0+aWQgPSBMVkxfRUFTWV9JRDsKCQlsZXZlbC0+bXVsdGkgPSBMVkxfRUFTWV9NVUxUSTsKCX0KCWVsc2UgewoJCWxldmVsLT5pZCA9IExWTF9IQVJEX0lEOwoJCWxldmVsLT5tdWx0aSA9IExWTF9IQVJEX01VTFRJOwoJfQoKCXJldHVybjsKfQoKLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQp2b2lkIGdldF9udHJpZXMoIGludCAqbnRyaWVzLCBjb25zdCBjaGFyICpmbXR0ZXh0ICkKewoJY2hhciBpbmJ1ZlsgTUFYSU5CVUYgXTsKCglkbyB7CgkJcHJpbnRmKCBmbXR0ZXh0LCBNSU5UUklFUywgTUFYVFJJRVMgKTsKCQlmZ2V0cyhpbmJ1ZiwgTUFYSU5CVUYsIHN0ZGluKTsKCQkqbnRyaWVzID0gYXRvaSggaW5idWYgKTsKCX0gd2hpbGUgKCAqbnRyaWVzIDwgTUlOVFJJRVMgfHwgKm50cmllcyA+IE1BWFRSSUVTKTsKCglyZXR1cm47Cn0KCi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KTXNnUG9zIGhpbnRfZ2V0cG9zKGNvbnN0IGludCBndWVzcywgY29uc3QgaW50IGhpZGRlbiwgY29uc3QgaW50IGxpbSwgY29uc3QgaW50IGxldmlkKQp7CglpbnQgZGlmZjsKCglpZiAoZ3Vlc3MgPiBsaW0gfHwgZ3Vlc3MgPCAxKQoJCXJldHVybiBUWFRfT1VUT0ZCT1VORFM7CgoJaWYgKGd1ZXNzID09IGhpZGRlbiApCgkJcmV0dXJuIFRYVF9DT05HUkFUUzsKCglpZiAoIGxldmlkID09IExWTF9IQVJEX0lEKQoJCXJldHVybiAoZ3Vlc3MgPCBoaWRkZW4pID8gVFhUX0hJR0hFUiA6IFRYVF9MT1dFUjsgCgoJZGlmZiA9IEFCUyhoaWRkZW4tZ3Vlc3MpOwoKCWlmIChndWVzcyA8IGhpZGRlbikKCXsKCQlpZiAoIGRpZmYgPD0gRElGRl9IT1QgKQoJCQlyZXR1cm4gVFhUX0hJR0hFUkhPVDsKCQlpZiAoIGRpZmYgPiBESUZGX0NPTEQgKQoJCQlyZXR1cm4gVFhUX0hJR0hFUkNPTEQ7CgkJcmV0dXJuIFRYVF9ISUdIRVI7Cgl9CgoJaWYgKGd1ZXNzID4gaGlkZGVuKQoJewoJCWlmICggZGlmZiA8PSBESUZGX0hPVCApCgkJCXJldHVybiBUWFRfTE9XRVJIT1Q7CgkJaWYgKCBkaWZmID4gRElGRl9DT0xEICkKCQkJcmV0dXJuIFRYVF9MT1dFUkNPTEQ7CgkJcmV0dXJuIFRYVF9MT1dFUjsKCX0KCglyZXR1cm4gVFhUX0NPTkdSQVRTOwp9Cg==