/* -------------------------------------------------------------------------
* Title: Target Points v1.0
* From: migf1
* Description:
* a little gambling, board game in text mode, written in ANSI C (C99)
* see function: show_help() for details
* Notes:
* the GameStatus structure is used for making it easy to add
* features like "save game" and "load game" in next versions
* -------------------------------------------------------------------------
*/
#include <stdio.h>
#include <string.h> // for strlen()
#include <stdlib.h> // for srand(), exit()
#include <ctype.h> // for isdigit()
#include <time.h> // for time() (used in srand())
#define MAXINBUF 255+1 // max chars we read in the input buffer
#define MAXPNAME 5+1 // max length for the player's name
#define MAXROWS 7 // board's max height
#define MAXCOLS 7 // board's max width
#define CREDITS() printf("%76s\n", "\"Target Points\" by migf1");
#define PROMPT(plr, mov, maxmovs, pts, maxpts) \
printf("[%s] M:%d/%d, P:%d/%d> ", (plr), (mov+1), (maxmovs), (pts), (maxpts) )
#define PAUSE() \
do{ \
char myinbufr[255]=""; \
printf("\npress ENTER..."); \
fgets(myinbufr, 255, stdin); \
}while(0)
typedef enum { FALSE=0, TRUE } Bool; // our custom boolean data type
typedef struct cell { // structure of any individual cell
Bool avail; // is it available for selection?
int pos; // cell's position in the board
int val; // cell's value
}Cell;
typedef struct game { // structure of the game itself
char player[ MAXPNAME ]; // player name
Cell board[ MAXROWS ][ MAXCOLS ]; // the board
int move, maxmoves; // current & max number of moves
int points, maxpoints; // current & max number of points
int score; // *** UNUSED ***
}GameStatus;
// ---------------------------------------------------------------------------------
void show_help( void )
{
puts("\n\tThis is a little gambling game written in ANSI C, by migf1.");
puts("\n\tYour task is to collect the target amount of points in as many"); puts("\tmoves as the half of the total cells of the board.");
puts("\n\tCells are initially populated with random values ranging from"); puts("\t0 to the total number of cells - 1 (e.g.: from 0 to 48 for a"); puts("\t7x7 board). Duplicated values may appear in two or more cells."); puts("\tThe target amount of points you are after, equals to the half"); puts("\tof the sum of all those values (sum of values / 2)");
puts("\n\tTo choose a cell you enter its positioning number, as shown"); puts("\tin the left diagram. The value it holds will appear in the"); puts("\tright diagram and it will be added to your current points.");
puts("\n\tIf you run out of moves before collecting the target amount"); puts("\tof points, the game ends and you get 0 score. If you manage"); puts("\tto collect the points before running out of moves, then the"); puts("\tpoints collected beyond the targeted amount are multiplied"); puts("\tby the moves you had left, and the result is your score");
puts("\n\tThe prompt always shows your current move and points, along");
PAUSE();
puts("\n\twith the moves you have left, and the targeted amount of"); puts("\tpoints to be gathered. So make sure you check it regularly"); puts("\t(M stands for move, P for points).");
puts("\n\tYou can also use the following commands at the prompt:"); puts("\th\tthis help you are reading right now"); puts("\tt\tshow current stats"); puts("\tx\texit the game (note: you'll get 0 score!)");
puts("\n\tThe game ends either when you run out of moves, you enter"); puts("\tx at the prompt, or you gather more points than the targeted"); puts("\tamount (equal or more). In any case, all the cell-values will"); puts("\tbe revealed in the right diagram, just before the termination"); puts("\tof the program.");
PAUSE();
return;
}
// ---------------------------------------------------------------------------------
// Show current statistics
//
void show_stats( int move, int maxmoves, int points, int maxpoints )
{
printf("\n\tyou've made %d move(s), having collected %d points\n", move
, points
); printf( "\tyou have %d move(s) left, to collect %d more point(s)\n\n", maxmoves-move, maxpoints-points
);
return;
}
// ---------------------------------------------------------------------------------
// Calculate and show the score on the screen, after the game has ended
//
void show_score( int points, int maxpoints, int move, int maxmoves, int *score)
{
if ( points >= maxpoints ) {
printf("\t\a\a*** YES, YOU MADE IT! You collected %d points in %d moves(s)\n", points
, move
); *score = (points - maxpoints + 1) * (maxmoves - move + 1);
printf("\t*** YOUR SCORE IS: %d\n", *score
); }
else {
*score = 0;
puts("\n\tSORRY, YOU FAILED! NO SCORE THIS TIME!"); }
return;
}
// ---------------------------------------------------------------------------------
// Read s from standard input
//
char *s_get(char *s, size_t len)
{
char *cp;
for (cp
=s
; (*cp
=getc(stdin
)) != '\n' && (cp
-s
) < len
-1; cp
++ ) ; // for-loop with empty body
*cp = '\0'; // null-terminate last character
return s;
}
// ---------------------------------------------------------------------------------
// Trim leading & trailing spaces from s
//
char *s_trim( char *s )
{
char *cp1; // for parsing the whole s
char *cp2; // for shifting & padding
// trim leading & shift left remaining
for (cp1
=s
; isspace(*cp1
); cp1
++ ) // skip leading spaces, via cp1 ;
for (cp2=s; *cp1; cp1++, cp2++) // shift left remaining chars, via cp2
*cp2 = *cp1;
*cp2-- = '\0'; // mark end of left trimmed s
// replace trailing spaces with '\0's
*cp2-- = '\0'; // pad with '\0'
return s;
}
// ---------------------------------------------------------------------------------
// Initialize the board (it also populates it with random cell-values)
//
int init_board( int nrows, int ncols, Cell board[nrows][ncols] )
{
register int i,j;
int valsum = 0;
for (i=0; i<nrows; i++)
{
for (j=0; j < ncols; j++) {
board[i][j].avail = TRUE;
board[i][j].pos = i * ncols + j;
board
[i
][j
].
val = rand() % (nrows
*ncols
); valsum += board[i][j].val;
}
}
return valsum;
}
// ---------------------------------------------------------------------------------
/*** DISABLED: UNUSED
void draw_board( int nrows, int ncols, Cell board[nrows][ncols] )
{
register int i,j;
for (i=0; i<nrows; i++)
{
for (j=0; j < ncols; j++)
printf("+---");
puts("+");
for (j=0; j < ncols; j++)
printf("| %2d ", board[i][j].val);
puts("|");
}
for (j=0; j < ncols; j++)
printf("+---");
puts("+");
return;
}
***/
// ---------------------------------------------------------------------------------
// Draw the board diagrams on the screen, the left one with available posistions,
// the right one with already selected cell-values (if cheat is TRUE, the right
// diagram shows ALL cell-values, instead).
//
void draw_status( int nrows, int ncols, Cell board[nrows][ncols], Bool cheat )
{
register int i,j;
for (i=0; i<nrows; i++)
{
for (j=0; j < ncols; j++)
for (j=0; j < ncols; j++)
for (j=0; j < ncols; j++)
{
if ( board[i][j].avail )
printf("| %2d ", board
[i
][j
].
pos); else
}
for (j=0; j < ncols; j++)
{
if ( board[i][j].avail && !cheat)
else
printf("| %2d ", board
[i
][j
].
val); }
}
for (j=0; j < ncols; j++)
for (j=0; j < ncols; j++)
return;
}
// ---------------------------------------------------------------------------------
// Read the player name form the standard input
//
char *get_player( char *player )
{
if ( !player )
return NULL;
int temp;
char dummy[MAXINBUF] = "";
do {
printf("Player name (%d chars, more will be ignored)? ", MAXPNAME
-1); s_get(dummy, MAXINBUF);
s_trim(dummy);
if ( temp+1 > MAXPNAME)
dummy[MAXPNAME-1] = '\0';
} while ( !*player );
return player;
}
// ---------------------------------------------------------------------------------
// Handle non-numerical commands (e.g.: h, t, x, etc)
//
void exec_charcmd( char c, int move, int maxmoves, int points, int maxpoints)
{
switch ( c )
{
case 'x':
case '\0':
break;
case 'h':
show_help();
break;
case 't':
show_stats(move, maxmoves, points, maxpoints);
break;
default:
puts("\a\n\tinvalid command, type h for help\n"); break;
}
return;
}
// ---------------------------------------------------------------------------------
// Handle numerical commands (expecting them to be board positions)
//
Bool exec_poscmd( char *inbuf, int nrows, int ncols, Cell board[nrows][ncols], int *move, int *points)
{
int i, j, pos;
if ( pos < 0 || pos > nrows*ncols-1 ) {
puts("\a\n\tinvalid position\n"); return FALSE;
}
i = pos / ncols;
j = pos % ncols;
if ( !board[ i ][ j ].avail ) {
puts("\a\n\tyou have already played that position\n"); return FALSE;
}
board[ i ][ j ].avail = FALSE;
(*move)++;
(*points) += board[ i ][ j ].val;
printf("\n\t%d points added to your bucket!\n\n", board
[ i
][ j
].
val);
return TRUE;
}
// ---------------------------------------------------------------------------------
int main( void )
{
char inbuf[MAXINBUF] = ""; // our input buffer
GameStatus game = { // our current game
.player = "",
// .board,
.move = 0, .maxmoves = (MAXROWS*MAXCOLS)/2,
.points = 0, .maxpoints = 0,
.score = 0
};
srand( time(NULL
) ); // init random generator // init target amount of points
game.maxpoints = init_board( MAXROWS, MAXCOLS, game.board ) / 2;
get_player( game.player ); // get player name
do { // the main loop of the game
draw_status( MAXROWS, MAXCOLS, game.board, FALSE );
CREDITS();
PROMPT( game.player, game.move, game.maxmoves, game.points, game.maxpoints );
s_get(inbuf, MAXINBUF); // get user command
s_trim( inbuf ); // (trim leading spaces)
exec_poscmd( inbuf, MAXROWS, MAXCOLS, game.board, &game.move, &game.points );
else // handle non-numerical commands
exec_charcmd( *inbuf, game.move, game.maxmoves, game.points, game.maxpoints );
} while( tolower(*inbuf
) != 'x' // game ends either when x && game.move < game.maxmoves // or run out of moves
&& game.points < game.maxpoints ); // or maxpoints have been reached
// display the final score
show_score( game.points, game.maxpoints, game.move, game.maxmoves, &game.score);
puts("\n\thave a look at the full board, before exiting\n"); draw_status( MAXROWS, MAXCOLS, game.board, TRUE );
PAUSE();
}
LyogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQogKiBUaXRsZTogVGFyZ2V0IFBvaW50cyB2MS4wCiAqIEZyb206IG1pZ2YxCiAqIERlc2NyaXB0aW9uOgogKglhIGxpdHRsZSBnYW1ibGluZywgYm9hcmQgZ2FtZSBpbiB0ZXh0IG1vZGUsIHdyaXR0ZW4gaW4gQU5TSSBDIChDOTkpCiAqCXNlZSBmdW5jdGlvbjogc2hvd19oZWxwKCkgZm9yIGRldGFpbHMKICogTm90ZXM6CiAqCXRoZSBHYW1lU3RhdHVzIHN0cnVjdHVyZSBpcyB1c2VkIGZvciBtYWtpbmcgaXQgZWFzeSB0byBhZGQKICoJZmVhdHVyZXMgbGlrZSAic2F2ZSBnYW1lIiBhbmQgImxvYWQgZ2FtZSIgaW4gbmV4dCB2ZXJzaW9ucwogKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCiAqLwoKI2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDxzdHJpbmcuaD4JCQkJLy8gZm9yIHN0cmxlbigpCiNpbmNsdWRlIDxzdGRsaWIuaD4JCQkJLy8gZm9yIHNyYW5kKCksIGV4aXQoKQojaW5jbHVkZSA8Y3R5cGUuaD4JCQkJLy8gZm9yIGlzZGlnaXQoKQojaW5jbHVkZSA8dGltZS5oPgkJCQkvLyBmb3IgdGltZSgpICh1c2VkIGluIHNyYW5kKCkpCgojZGVmaW5lIE1BWElOQlVGCTI1NSsxCQkJLy8gbWF4IGNoYXJzIHdlIHJlYWQgaW4gdGhlIGlucHV0IGJ1ZmZlcgojZGVmaW5lIE1BWFBOQU1FCTUrMQkJCS8vIG1heCBsZW5ndGggZm9yIHRoZSBwbGF5ZXIncyBuYW1lCgojZGVmaW5lIE1BWFJPV1MJCTcJCQkvLyBib2FyZCdzIG1heCBoZWlnaHQKI2RlZmluZSBNQVhDT0xTCQk3CQkJLy8gYm9hcmQncyBtYXggd2lkdGgKCiNkZWZpbmUgQ1JFRElUUygpCXByaW50ZigiJTc2c1xuIiwgIlwiVGFyZ2V0IFBvaW50c1wiIGJ5IG1pZ2YxIik7CgojZGVmaW5lIFBST01QVChwbHIsIG1vdiwgbWF4bW92cywgcHRzLCBtYXhwdHMpCVwKCXByaW50ZigiWyVzXSBNOiVkLyVkLCBQOiVkLyVkPiAiLCAocGxyKSwgKG1vdisxKSwgKG1heG1vdnMpLCAocHRzKSwgKG1heHB0cykgKQoKI2RlZmluZSBQQVVTRSgpCQkJCQlcCglkb3sJCQkJCVwKCQljaGFyIG15aW5idWZyWzI1NV09IiI7CQlcCgkJcHJpbnRmKCJcbnByZXNzIEVOVEVSLi4uIik7CVwKCQlmZ2V0cyhteWluYnVmciwgMjU1LCBzdGRpbik7CVwKCX13aGlsZSgwKQoKdHlwZWRlZiBlbnVtIHsgRkFMU0U9MCwgVFJVRSB9IEJvb2w7CQkvLyBvdXIgY3VzdG9tIGJvb2xlYW4gZGF0YSB0eXBlCgp0eXBlZGVmIHN0cnVjdCBjZWxsIHsJCQkJLy8gc3RydWN0dXJlIG9mIGFueSBpbmRpdmlkdWFsIGNlbGwKCUJvb2wgYXZhaWw7CQkJCS8vCWlzIGl0IGF2YWlsYWJsZSBmb3Igc2VsZWN0aW9uPwoJaW50IHBvczsJCQkJLy8JY2VsbCdzIHBvc2l0aW9uIGluIHRoZSBib2FyZAoJaW50IHZhbDsJCQkJLy8JY2VsbCdzIHZhbHVlCn1DZWxsOwoKdHlwZWRlZiBzdHJ1Y3QgZ2FtZSB7CQkJCS8vIHN0cnVjdHVyZSBvZiB0aGUgZ2FtZSBpdHNlbGYKCWNoYXIgcGxheWVyWyBNQVhQTkFNRSBdOwkJLy8JcGxheWVyIG5hbWUKCUNlbGwgYm9hcmRbIE1BWFJPV1MgXVsgTUFYQ09MUyBdOwkvLwl0aGUgYm9hcmQKCWludCBtb3ZlLCBtYXhtb3ZlczsJCQkvLwljdXJyZW50ICYgbWF4IG51bWJlciBvZiBtb3ZlcwoJaW50IHBvaW50cywgbWF4cG9pbnRzOwkJCS8vCWN1cnJlbnQgJiBtYXggbnVtYmVyIG9mIHBvaW50cwoJaW50IHNjb3JlOwkJCQkvLwkqKiogVU5VU0VEICoqKgp9R2FtZVN0YXR1czsKCi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQp2b2lkIHNob3dfaGVscCggdm9pZCApCnsKCXB1dHMoIlxuXHRUaGlzIGlzIGEgbGl0dGxlIGdhbWJsaW5nIGdhbWUgd3JpdHRlbiBpbiBBTlNJIEMsIGJ5IG1pZ2YxLiIpOwoKCXB1dHMoIlxuXHRZb3VyIHRhc2sgaXMgdG8gY29sbGVjdCB0aGUgdGFyZ2V0IGFtb3VudCBvZiBwb2ludHMgaW4gYXMgbWFueSIpOwoJcHV0cygiXHRtb3ZlcyBhcyB0aGUgaGFsZiBvZiB0aGUgdG90YWwgY2VsbHMgb2YgdGhlIGJvYXJkLiIpOwoKCXB1dHMoIlxuXHRDZWxscyBhcmUgaW5pdGlhbGx5IHBvcHVsYXRlZCB3aXRoIHJhbmRvbSB2YWx1ZXMgcmFuZ2luZyBmcm9tIik7CglwdXRzKCJcdDAgdG8gdGhlIHRvdGFsIG51bWJlciBvZiBjZWxscyAtIDEgKGUuZy46IGZyb20gMCB0byA0OCBmb3IgYSIpOwoJcHV0cygiXHQ3eDcgYm9hcmQpLiBEdXBsaWNhdGVkIHZhbHVlcyBtYXkgYXBwZWFyIGluIHR3byBvciBtb3JlIGNlbGxzLiIpOwoJcHV0cygiXHRUaGUgdGFyZ2V0IGFtb3VudCBvZiBwb2ludHMgeW91IGFyZSBhZnRlciwgZXF1YWxzIHRvIHRoZSBoYWxmIik7CglwdXRzKCJcdG9mIHRoZSBzdW0gb2YgYWxsIHRob3NlIHZhbHVlcyAoc3VtIG9mIHZhbHVlcyAvIDIpIik7CgoJcHV0cygiXG5cdFRvIGNob29zZSBhIGNlbGwgeW91IGVudGVyIGl0cyBwb3NpdGlvbmluZyBudW1iZXIsIGFzIHNob3duIik7CglwdXRzKCJcdGluIHRoZSBsZWZ0IGRpYWdyYW0uIFRoZSB2YWx1ZSBpdCBob2xkcyB3aWxsIGFwcGVhciBpbiB0aGUiKTsKCXB1dHMoIlx0cmlnaHQgZGlhZ3JhbSBhbmQgaXQgd2lsbCBiZSBhZGRlZCB0byB5b3VyIGN1cnJlbnQgcG9pbnRzLiIpOwoKCXB1dHMoIlxuXHRJZiB5b3UgcnVuIG91dCBvZiBtb3ZlcyBiZWZvcmUgY29sbGVjdGluZyB0aGUgdGFyZ2V0IGFtb3VudCIpOwoJcHV0cygiXHRvZiBwb2ludHMsIHRoZSBnYW1lIGVuZHMgYW5kIHlvdSBnZXQgMCBzY29yZS4gSWYgeW91IG1hbmFnZSIpOwoJcHV0cygiXHR0byBjb2xsZWN0IHRoZSBwb2ludHMgYmVmb3JlIHJ1bm5pbmcgb3V0IG9mIG1vdmVzLCB0aGVuIHRoZSIpOwoJcHV0cygiXHRwb2ludHMgY29sbGVjdGVkIGJleW9uZCB0aGUgdGFyZ2V0ZWQgYW1vdW50IGFyZSBtdWx0aXBsaWVkIik7CglwdXRzKCJcdGJ5IHRoZSBtb3ZlcyB5b3UgaGFkIGxlZnQsIGFuZCB0aGUgcmVzdWx0IGlzIHlvdXIgc2NvcmUiKTsKCglwdXRzKCJcblx0VGhlIHByb21wdCBhbHdheXMgc2hvd3MgeW91ciBjdXJyZW50IG1vdmUgYW5kIHBvaW50cywgYWxvbmciKTsKCglQQVVTRSgpOwoKCXB1dHMoIlxuXHR3aXRoIHRoZSBtb3ZlcyB5b3UgaGF2ZSBsZWZ0LCBhbmQgdGhlIHRhcmdldGVkIGFtb3VudCBvZiIpOwoJcHV0cygiXHRwb2ludHMgdG8gYmUgZ2F0aGVyZWQuIFNvIG1ha2Ugc3VyZSB5b3UgY2hlY2sgaXQgcmVndWxhcmx5Iik7CglwdXRzKCJcdChNIHN0YW5kcyBmb3IgbW92ZSwgUCBmb3IgcG9pbnRzKS4iKTsKCglwdXRzKCJcblx0WW91IGNhbiBhbHNvIHVzZSB0aGUgZm9sbG93aW5nIGNvbW1hbmRzIGF0IHRoZSBwcm9tcHQ6Iik7CglwdXRzKCIiKTsKCXB1dHMoIlx0aFx0dGhpcyBoZWxwIHlvdSBhcmUgcmVhZGluZyByaWdodCBub3ciKTsKCXB1dHMoIlx0dFx0c2hvdyBjdXJyZW50IHN0YXRzIik7CglwdXRzKCJcdHhcdGV4aXQgdGhlIGdhbWUgKG5vdGU6IHlvdSdsbCBnZXQgMCBzY29yZSEpIik7CgoJcHV0cygiXG5cdFRoZSBnYW1lIGVuZHMgZWl0aGVyIHdoZW4geW91IHJ1biBvdXQgb2YgbW92ZXMsIHlvdSBlbnRlciIpOwoJcHV0cygiXHR4IGF0IHRoZSBwcm9tcHQsIG9yIHlvdSBnYXRoZXIgbW9yZSBwb2ludHMgdGhhbiB0aGUgdGFyZ2V0ZWQiKTsKCXB1dHMoIlx0YW1vdW50IChlcXVhbCBvciBtb3JlKS4gSW4gYW55IGNhc2UsIGFsbCB0aGUgY2VsbC12YWx1ZXMgd2lsbCIpOwoJcHV0cygiXHRiZSByZXZlYWxlZCBpbiB0aGUgcmlnaHQgZGlhZ3JhbSwganVzdCBiZWZvcmUgdGhlIHRlcm1pbmF0aW9uIik7CglwdXRzKCJcdG9mIHRoZSBwcm9ncmFtLiIpOwoKCXB1dHMoIlxuXHRIYXZlIGZ1biEiKTsKCglQQVVTRSgpOwoKCXJldHVybjsKfQoKLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCi8vIFNob3cgY3VycmVudCBzdGF0aXN0aWNzCi8vCnZvaWQgc2hvd19zdGF0cyggaW50IG1vdmUsIGludCBtYXhtb3ZlcywgaW50IHBvaW50cywgaW50IG1heHBvaW50cyApCnsKCXByaW50ZigiXG5cdHlvdSd2ZSBtYWRlICVkIG1vdmUocyksIGhhdmluZyBjb2xsZWN0ZWQgJWQgcG9pbnRzXG4iLCBtb3ZlLCBwb2ludHMJKTsKCXByaW50ZigJIlx0eW91IGhhdmUgJWQgbW92ZShzKSBsZWZ0LCB0byBjb2xsZWN0ICVkIG1vcmUgcG9pbnQocylcblxuIiwKCQltYXhtb3Zlcy1tb3ZlLCBtYXhwb2ludHMtcG9pbnRzCgkpOwoKCXJldHVybjsKfQoKLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCi8vIENhbGN1bGF0ZSBhbmQgc2hvdyB0aGUgc2NvcmUgb24gdGhlIHNjcmVlbiwgYWZ0ZXIgdGhlIGdhbWUgaGFzIGVuZGVkCi8vCnZvaWQgc2hvd19zY29yZSggaW50IHBvaW50cywgaW50IG1heHBvaW50cywgaW50IG1vdmUsIGludCBtYXhtb3ZlcywgaW50ICpzY29yZSkKewoJaWYgKCBwb2ludHMgPj0gbWF4cG9pbnRzICkgewoJCXByaW50ZigiXHRcYVxhKioqIFlFUywgWU9VIE1BREUgSVQhIFlvdSBjb2xsZWN0ZWQgJWQgcG9pbnRzIGluICVkIG1vdmVzKHMpXG4iLCBwb2ludHMsIG1vdmUpOwoJCSpzY29yZSA9IChwb2ludHMgLSBtYXhwb2ludHMgKyAxKSAqIChtYXhtb3ZlcyAtIG1vdmUgKyAxKTsKCQlwcmludGYoIlx0KioqIFlPVVIgU0NPUkUgSVM6ICVkXG4iLCAqc2NvcmUpOwoJfQoJZWxzZSB7CgkJKnNjb3JlID0gMDsKCQlwdXRzKCJcblx0U09SUlksIFlPVSBGQUlMRUQhIE5PIFNDT1JFIFRISVMgVElNRSEiKTsKCX0KCglyZXR1cm47Cn0KCi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQovLyBSZWFkIHMgZnJvbSBzdGFuZGFyZCBpbnB1dAovLwpjaGFyICpzX2dldChjaGFyICpzLCBzaXplX3QgbGVuKQp7CiAgICAgICAgY2hhciAqY3A7CgogICAgICAgIGZvciAoY3A9czsgKCpjcD1nZXRjKHN0ZGluKSkgIT0gJ1xuJyAmJiAoY3AtcykgPCBsZW4tMTsgY3ArKyApCiAgICAgICAgICAgICAgICA7CQkJCQkvLyBmb3ItbG9vcCB3aXRoIGVtcHR5IGJvZHkKICAgICAgICAqY3AgPSAnXDAnOwkJCQkJLy8gbnVsbC10ZXJtaW5hdGUgbGFzdCBjaGFyYWN0ZXIKCiAgICAgICAgcmV0dXJuIHM7Cn0KCi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQovLyBUcmltIGxlYWRpbmcgJiB0cmFpbGluZyBzcGFjZXMgZnJvbSBzCi8vCmNoYXIgKnNfdHJpbSggY2hhciAqcyApCnsKCWNoYXIgKmNwMTsJCQkJCS8vIGZvciBwYXJzaW5nIHRoZSB3aG9sZSBzCgljaGFyICpjcDI7CQkJCQkvLyBmb3Igc2hpZnRpbmcgJiBwYWRkaW5nCgoJLy8gdHJpbSBsZWFkaW5nICYgc2hpZnQgbGVmdCByZW1haW5pbmcKCWZvciAoY3AxPXM7IGlzc3BhY2UoKmNwMSk7IGNwMSsrICkJCS8vIHNraXAgbGVhZGluZyBzcGFjZXMsIHZpYSBjcDEKCQk7Cglmb3IgKGNwMj1zOyAqY3AxOyBjcDErKywgY3AyKyspCQkJLy8gc2hpZnQgbGVmdCByZW1haW5pbmcgY2hhcnMsIHZpYSBjcDIKCQkqY3AyID0gKmNwMTsKCSpjcDItLSA9ICdcMCc7CQkJCQkvLyBtYXJrIGVuZCBvZiBsZWZ0IHRyaW1tZWQgcwoKCS8vIHJlcGxhY2UgdHJhaWxpbmcgc3BhY2VzIHdpdGggJ1wwJ3MKCXdoaWxlICggY3AyID4gcyAmJiBpc3NwYWNlKCpjcDIpICkKCQkqY3AyLS0gPSAnXDAnOwkJCQkvLyBwYWQgd2l0aCAnXDAnCgoJcmV0dXJuIHM7Cn0KCi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQovLyBJbml0aWFsaXplIHRoZSBib2FyZCAoaXQgYWxzbyBwb3B1bGF0ZXMgaXQgd2l0aCByYW5kb20gY2VsbC12YWx1ZXMpCi8vCmludCBpbml0X2JvYXJkKCBpbnQgbnJvd3MsIGludCBuY29scywgQ2VsbCBib2FyZFtucm93c11bbmNvbHNdICkKewoJcmVnaXN0ZXIgaW50IGksajsKCWludCB2YWxzdW0gPSAwOwoKCWZvciAoaT0wOyBpPG5yb3dzOyBpKyspCgl7CgkJZm9yIChqPTA7IGogPCBuY29sczsgaisrKSB7CgkJCWJvYXJkW2ldW2pdLmF2YWlsID0gVFJVRTsKCQkJYm9hcmRbaV1bal0ucG9zID0gaSAqIG5jb2xzICsgajsKCQkJYm9hcmRbaV1bal0udmFsID0gcmFuZCgpICUgKG5yb3dzKm5jb2xzKTsKCQkJdmFsc3VtICs9IGJvYXJkW2ldW2pdLnZhbDsKCQl9Cgl9CgoJcmV0dXJuIHZhbHN1bTsKfQoKLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCi8qKiogRElTQUJMRUQ6IFVOVVNFRAoKdm9pZCBkcmF3X2JvYXJkKCBpbnQgbnJvd3MsIGludCBuY29scywgQ2VsbCBib2FyZFtucm93c11bbmNvbHNdICkKewoJcmVnaXN0ZXIgaW50IGksajsKCglmb3IgKGk9MDsgaTxucm93czsgaSsrKQoJewoJCWZvciAoaj0wOyBqIDwgbmNvbHM7IGorKykKCQkJcHJpbnRmKCIrLS0tIik7CgkJcHV0cygiKyIpOwoJCWZvciAoaj0wOyBqIDwgbmNvbHM7IGorKykKCQkJcHJpbnRmKCJ8ICUyZCAiLCBib2FyZFtpXVtqXS52YWwpOwoJCXB1dHMoInwiKTsKCX0KCWZvciAoaj0wOyBqIDwgbmNvbHM7IGorKykKCQlwcmludGYoIistLS0iKTsKCXB1dHMoIisiKTsKCglyZXR1cm47Cn0KKioqLwoKLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCi8vIERyYXcgdGhlIGJvYXJkIGRpYWdyYW1zIG9uIHRoZSBzY3JlZW4sIHRoZSBsZWZ0IG9uZSB3aXRoIGF2YWlsYWJsZSBwb3Npc3Rpb25zLAovLyB0aGUgcmlnaHQgb25lIHdpdGggYWxyZWFkeSBzZWxlY3RlZCBjZWxsLXZhbHVlcyAoaWYgY2hlYXQgaXMgVFJVRSwgdGhlIHJpZ2h0Ci8vIGRpYWdyYW0gc2hvd3MgQUxMIGNlbGwtdmFsdWVzLCBpbnN0ZWFkKS4KLy8Kdm9pZCBkcmF3X3N0YXR1cyggaW50IG5yb3dzLCBpbnQgbmNvbHMsIENlbGwgYm9hcmRbbnJvd3NdW25jb2xzXSwgQm9vbCBjaGVhdCApCnsKCXJlZ2lzdGVyIGludCBpLGo7CgoJZm9yIChpPTA7IGk8bnJvd3M7IGkrKykKCXsKCQlmb3IgKGo9MDsgaiA8IG5jb2xzOyBqKyspCgkJCXByaW50ZigifC0tLS0iKTsKCQlwcmludGYoInxcdCIpOwoJCWZvciAoaj0wOyBqIDwgbmNvbHM7IGorKykKCQkJcHJpbnRmKCItLS0tLSIpOwoJCXB1dHMoIi0iKTsKCgkJZm9yIChqPTA7IGogPCBuY29sczsgaisrKQoJCXsKCQkJaWYgKCBib2FyZFtpXVtqXS5hdmFpbCApCgkJCQlwcmludGYoInwgJTJkICIsIGJvYXJkW2ldW2pdLnBvcyk7CgkJCWVsc2UKCQkJCXByaW50ZigifCAjIyAiKTsKCQl9CgkJcHJpbnRmKCJ8XHQiKTsKCQlmb3IgKGo9MDsgaiA8IG5jb2xzOyBqKyspCgkJewoJCQlpZiAoIGJvYXJkW2ldW2pdLmF2YWlsICYmICFjaGVhdCkKCQkJCXByaW50ZigifCAgICAiKTsKCQkJZWxzZQoJCQkJcHJpbnRmKCJ8ICUyZCAiLCBib2FyZFtpXVtqXS52YWwpOwoJCX0KCQlwdXRzKCJ8Iik7Cgl9Cglmb3IgKGo9MDsgaiA8IG5jb2xzOyBqKyspCgkJcHJpbnRmKCJ8LS0tLSIpOwoJcHJpbnRmKCJ8XHQiKTsKCWZvciAoaj0wOyBqIDwgbmNvbHM7IGorKykKCQlwcmludGYoIi0tLS0tIik7CglwdXRzKCItIik7CgoJcmV0dXJuOwp9CgovLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KLy8gUmVhZCB0aGUgcGxheWVyIG5hbWUgZm9ybSB0aGUgc3RhbmRhcmQgaW5wdXQKLy8KY2hhciAqZ2V0X3BsYXllciggY2hhciAqcGxheWVyICkKewoJaWYgKCAhcGxheWVyICkKCQlyZXR1cm4gTlVMTDsKCglpbnQgdGVtcDsKCWNoYXIgZHVtbXlbTUFYSU5CVUZdID0gIiI7CgoJZG8gewoJCXByaW50ZigiUGxheWVyIG5hbWUgKCVkIGNoYXJzLCBtb3JlIHdpbGwgYmUgaWdub3JlZCk/ICIsIE1BWFBOQU1FLTEpOwoJCXNfZ2V0KGR1bW15LCBNQVhJTkJVRik7CgkJc190cmltKGR1bW15KTsKCQl0ZW1wID0gc3RybGVuKGR1bW15KTsKCQlpZiAoIHRlbXArMSA+IE1BWFBOQU1FKQoJCQlkdW1teVtNQVhQTkFNRS0xXSA9ICdcMCc7CgkJc3RyY3B5KHBsYXllciwgZHVtbXkpOwoJfSB3aGlsZSAoICEqcGxheWVyICk7CgoJcmV0dXJuIHBsYXllcjsKfQoKLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCi8vIEhhbmRsZSBub24tbnVtZXJpY2FsIGNvbW1hbmRzIChlLmcuOiBoLCB0LCB4LCBldGMpCi8vCnZvaWQgZXhlY19jaGFyY21kKCBjaGFyIGMsIGludCBtb3ZlLCBpbnQgbWF4bW92ZXMsIGludCBwb2ludHMsIGludCBtYXhwb2ludHMpCnsKCXN3aXRjaCAoIGMgKQoJewoJCWNhc2UgJ3gnOgoJCWNhc2UgJ1wwJzoKCQkJYnJlYWs7CgoJCWNhc2UgJ2gnOgoJCQlzaG93X2hlbHAoKTsKCQkJYnJlYWs7CgoJCWNhc2UgJ3QnOgoJCQlzaG93X3N0YXRzKG1vdmUsIG1heG1vdmVzLCBwb2ludHMsIG1heHBvaW50cyk7CgkJCWJyZWFrOwoKCQlkZWZhdWx0OgoJCQlwdXRzKCJcYVxuXHRpbnZhbGlkIGNvbW1hbmQsIHR5cGUgaCBmb3IgaGVscFxuIik7CgkJCWJyZWFrOwoJfQoKCXJldHVybjsKfQoKLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCi8vIEhhbmRsZSBudW1lcmljYWwgY29tbWFuZHMgKGV4cGVjdGluZyB0aGVtIHRvIGJlIGJvYXJkIHBvc2l0aW9ucykKLy8KQm9vbCBleGVjX3Bvc2NtZCggY2hhciAqaW5idWYsIGludCBucm93cywgaW50IG5jb2xzLCBDZWxsIGJvYXJkW25yb3dzXVtuY29sc10sIGludCAqbW92ZSwgaW50ICpwb2ludHMpCnsKCWludCBpLCBqLCBwb3M7CgoJcG9zID0gYXRvaSggaW5idWYgKTsKCWlmICggcG9zIDwgMCB8fCBwb3MgPiBucm93cypuY29scy0xICkgewoJCXB1dHMoIlxhXG5cdGludmFsaWQgcG9zaXRpb25cbiIpOwoJCXJldHVybiBGQUxTRTsKCX0KCglpID0gcG9zIC8gbmNvbHM7CglqID0gcG9zICUgbmNvbHM7CglpZiAoICFib2FyZFsgaSBdWyBqIF0uYXZhaWwgKSB7CgkJcHV0cygiXGFcblx0eW91IGhhdmUgYWxyZWFkeSBwbGF5ZWQgdGhhdCBwb3NpdGlvblxuIik7CgkJcmV0dXJuIEZBTFNFOwoJfQoKCWJvYXJkWyBpIF1bIGogXS5hdmFpbCA9IEZBTFNFOwoJKCptb3ZlKSsrOwoJKCpwb2ludHMpICs9IGJvYXJkWyBpIF1bIGogXS52YWw7CglwcmludGYoIlxuXHQlZCBwb2ludHMgYWRkZWQgdG8geW91ciBidWNrZXQhXG5cbiIsIGJvYXJkWyBpIF1bIGogXS52YWwpOwoKCXJldHVybiBUUlVFOwp9CgovLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KaW50IG1haW4oIHZvaWQgKQp7CgljaGFyIGluYnVmW01BWElOQlVGXSA9ICIiOwkJCS8vIG91ciBpbnB1dCBidWZmZXIKCUdhbWVTdGF0dXMgZ2FtZSA9IHsJCQkJLy8gb3VyIGN1cnJlbnQgZ2FtZQoJCS5wbGF5ZXIgPSAiIiwKCQkvLyAuYm9hcmQsCgkJLm1vdmUgPSAwLCAubWF4bW92ZXMgPSAoTUFYUk9XUypNQVhDT0xTKS8yLAoJCS5wb2ludHMgPSAwLCAubWF4cG9pbnRzID0gMCwKCQkuc2NvcmUgPSAwCgl9OwoKCXNyYW5kKCB0aW1lKE5VTEwpICk7CQkJCS8vIGluaXQgcmFuZG9tIGdlbmVyYXRvcgoJCQkJCQkJLy8gaW5pdCB0YXJnZXQgYW1vdW50IG9mIHBvaW50cwoJZ2FtZS5tYXhwb2ludHMgPSBpbml0X2JvYXJkKCBNQVhST1dTLCBNQVhDT0xTLCBnYW1lLmJvYXJkICkgLyAyOwoJZ2V0X3BsYXllciggZ2FtZS5wbGF5ZXIgKTsJCQkvLyBnZXQgcGxheWVyIG5hbWUKCglkbyB7CQkJCQkJLy8gdGhlIG1haW4gbG9vcCBvZiB0aGUgZ2FtZQoJCWRyYXdfc3RhdHVzKCBNQVhST1dTLCBNQVhDT0xTLCBnYW1lLmJvYXJkLCBGQUxTRSApOwoJCUNSRURJVFMoKTsKCgkJUFJPTVBUKCBnYW1lLnBsYXllciwgZ2FtZS5tb3ZlLCBnYW1lLm1heG1vdmVzLCBnYW1lLnBvaW50cywgZ2FtZS5tYXhwb2ludHMgKTsKCQlzX2dldChpbmJ1ZiwgTUFYSU5CVUYpOwkJCS8vIGdldCB1c2VyIGNvbW1hbmQKCQlzX3RyaW0oIGluYnVmICk7CQkJLy8gKHRyaW0gbGVhZGluZyBzcGFjZXMpCgoJCWlmICggaXNkaWdpdCggdG9sb3dlcigqaW5idWYpICkgKQkvLyBoYW5kbGUgbnVtZXJpY2FsIGNvbW1hbmRzCgkJCWV4ZWNfcG9zY21kKCBpbmJ1ZiwgTUFYUk9XUywgTUFYQ09MUywgZ2FtZS5ib2FyZCwgJmdhbWUubW92ZSwgJmdhbWUucG9pbnRzICk7CgkJZWxzZQkJCQkJLy8gaGFuZGxlIG5vbi1udW1lcmljYWwgY29tbWFuZHMKCQkJZXhlY19jaGFyY21kKCAqaW5idWYsIGdhbWUubW92ZSwgZ2FtZS5tYXhtb3ZlcywgZ2FtZS5wb2ludHMsIGdhbWUubWF4cG9pbnRzICk7CgoJfSB3aGlsZSggdG9sb3dlcigqaW5idWYpICE9ICd4JwkJCS8vIGdhbWUgZW5kcyBlaXRoZXIgd2hlbiB4CgkJJiYgZ2FtZS5tb3ZlIDwgZ2FtZS5tYXhtb3ZlcwkJLy8gb3IgcnVuIG91dCBvZiBtb3ZlcwoJCSYmIGdhbWUucG9pbnRzIDwgZ2FtZS5tYXhwb2ludHMgKTsJLy8gb3IgbWF4cG9pbnRzIGhhdmUgYmVlbiByZWFjaGVkCgoJCQkJCQkJLy8gZGlzcGxheSB0aGUgZmluYWwgc2NvcmUKCXNob3dfc2NvcmUoIGdhbWUucG9pbnRzLCBnYW1lLm1heHBvaW50cywgZ2FtZS5tb3ZlLCBnYW1lLm1heG1vdmVzLCAmZ2FtZS5zY29yZSk7CgoJcHV0cygiXG5cdGhhdmUgYSBsb29rIGF0IHRoZSBmdWxsIGJvYXJkLCBiZWZvcmUgZXhpdGluZ1xuIik7CglkcmF3X3N0YXR1cyggTUFYUk9XUywgTUFYQ09MUywgZ2FtZS5ib2FyZCwgVFJVRSApOwoKCVBBVVNFKCk7CglleGl0KCBFWElUX1NVQ0NFU1MgKTsKfQo=