<mosaic.cnfolio.com>
PROGRAM
  1. /* ### PSUEDO CODE ###
  2.  
  3. START
  4.   Populate the list with all the infomation about the valid bets
  5.  
  6.   ### Reading input ###
  7.  
  8.   WHILE 4 pairs haven't been read
  9.  
  10.       Read a bet name
  11.       Read a bet amount
  12.  
  13.     Move to the next pair
  14.  
  15.   END WHILE
  16.  
  17.   ### Converting to uppercase ###
  18.  
  19.   WHILE there are bet names left
  20.      
  21.       Convert all the letters in the bet name to uppercase
  22.       Move to the next bet name
  23.      
  24.   END WHILE
  25.  
  26.   ### Detecting the bets ###
  27.  
  28.   WHILE there are bet names left
  29.  
  30.       WHILE bet number < number of valid bets in the list
  31.      
  32.           IF the bet name matches the valid bet on the list
  33.               THEN
  34.                   Store the valid bet number
  35.                  
  36.                   Stop comparing this bet name against the list
  37.           END IF
  38.          
  39.           Increase bet number by 1
  40.       END WHILE
  41.  
  42.       IF the bet name didn't match any valid bet
  43.           THEN
  44.               Error + 1
  45.               Output an error message
  46.              
  47.               Stop checking any more bet names
  48.              
  49.       END IF
  50.      
  51.       Move to the next bet name
  52.      
  53.   END WHILE
  54.  
  55.   ### Checking bet amounts ###
  56.  
  57.   WHILE there are bet amounts left AND No errors have occured
  58.      
  59.       IF the bet amount is not a whole positive number
  60.           THEN
  61.               Error + 1
  62.               Output an error message
  63.          
  64.               Stop checking any more bet amounts
  65.       END IF
  66.          
  67.           Move to the next bet amount
  68.          
  69.   END WHILE
  70.  
  71.   ### Spinning the wheel and checking if player has won ###
  72.      
  73.   IF no errors have occured
  74.  
  75.       WHILE there are bets left
  76.           THEN
  77.              
  78.               Pick a random position on the roulette wheel
  79.              
  80.               WHILE there are still positions that the bet wins on
  81.                  
  82.                   IF the random position matches the position the bet wins on
  83.                       THEN
  84.                           Amount won = amount bet + the amount bet * the odds of the bet placed
  85.                          
  86.                           subtotal = subtotal + amount won
  87.                          
  88.                           Generate the output text which tells the player
  89.                               They won, where they placed their bet,
  90.                               the amount they bet, the amount they won
  91.                               their profit and their current subtotal
  92.                          
  93.                           Error = 0
  94.                       ELSE
  95.                           Error = 1
  96.                   END IF
  97.                  
  98.                   Move to the next position the bet wins on
  99.                  
  100.               END WHILE
  101.              
  102.               IF Error is 1
  103.                   THEN
  104.                       amount won is 0
  105.                      
  106.                       subtotal = subtotal - amount bet
  107.                      
  108.                       Generate the output text which tells the player
  109.                               They lost, where they placed their bet,
  110.                               the amount they bet, the amount they lost
  111.                               their profit and their current subtotal
  112.                      
  113.               END IF
  114.              
  115.       Move to the next bet
  116.      
  117.       END WHILE
  118.      
  119.       Generate the text which tells the player, the total amount: bet, won, and  total profit
  120.  
  121.         START Rendering Graphics
  122.             Calculate the starting position for the 4 balls
  123.            
  124.             WHILE there are frames remaining
  125.                 Create the frame
  126.                
  127.                 Draw the roulette wheel
  128.                 Draw the numbers of the roulette wheel
  129.                
  130.                 IF the frame number is < 30
  131.                     THEN
  132.                         WHILE there are still balls to draw
  133.                             Increase the ball's angle
  134.                             Set the balls radius
  135.                            
  136.                             Calculate the ball's X position based on radius and angle
  137.                             Calculate the ball's Y position based on radius and angle
  138.                            
  139.                             Draw the ball at the X and Y position
  140.                             Draw the ball's number in the centre
  141.                         END WHILE
  142.                        
  143.                     ELSE
  144.                         WHILE there are still balls to draw
  145.                             Increase the ball's angle by a factor
  146.                             Decrease the ball's radius by a factor
  147.                            
  148.                             Calculate the ball's X position based on radius and angle
  149.                             Calculate the ball's Y position based on radius and angle
  150.                            
  151.                             Draw the ball at the X and Y position
  152.                             Draw the ball's number in the centre
  153.                            
  154.                             IF the factor is to small
  155.                                 THEN
  156.                                     Increase the factor
  157.                             END IF
  158.                         END WHILE
  159.                 END IF
  160.                
  161.                 WHILE there are lines of output text left
  162.                     Draw the line of output text
  163.                     Move to the next output text line
  164.                 END WHILE
  165.            
  166.                 Draw the roulette table
  167.                 Draw the numbers on the roulette table
  168.                
  169.                 WHILE there are chips left to draw
  170.                     Draw the chip based on the X and Y position stored in the list
  171.                      Move to the next chip
  172.                 END WHILE
  173.            
  174.                 Save the frame
  175.                 Move to the next frame
  176.             END WHILE
  177.         END Rendering Graphics
  178.      
  179.       ELSE
  180.         Output error messages
  181.         Output a message telling the player the valid bets and how to input them
  182.        
  183.   END IF
  184.  
  185. END
  186.  
  187. */
  188. #include <stdio.h>
  189. #include <stdlib.h>
  190. #include <string.h>
  191. #include <time.h>
  192.  
  193. #include <gd.h>
  194.  
  195. #define numofbets       152 /* This is defined pre-program as any inconsistency will result in Fatal Runtime errors that are a pain to locate */
  196. #define numofoutlines   10 /* Same again */
  197.  
  198. #define  framewidth  1000
  199. #define  frameheight   560
  200. #define  maxframecount 90
  201. #define  frametime    12
  202.  
  203. #define PI (3.141592653589793)
  204.  
  205. struct libary {
  206.    char  name[18];
  207.    int   odds;
  208.    int   numofnums; /* This defines how long the array of numbers bet on will be, see below */
  209.    int   *numbers; /* This is not declared as a fixed lenght array as there is many different types of bets that bet of different quanties of numbers */
  210.    int   coords[2]; /* Array contains the x and y coordinates of the position on boards that bet chip will be placed on */
  211. }  betlibary[numofbets];
  212.  
  213. void loadbet( int, char[], int, int,int,int);
  214. void loadlibary( void );
  215. void graphics( int ballnumbers[4], int *ptr, FILE *fp ); /* The frame pointer and file pointer have to be past to the function */
  216.  
  217. int tempnumbers[20], position=0, word=0, spaces=0, betnum = 0,error=0, dash=0;
  218. int bet[4] = { -1,-1,-1,-1 };
  219. char outputtext[numofoutlines][128];
  220.  
  221. int main( void ){
  222.  
  223.    int i=0, j=0;
  224.    int amountbet[4] = { -1,-1,-1,-1 };
  225.    int amountwon[4] = { 0 };
  226.    char inputraw[8][18];
  227.    int wheel[4] = {0};
  228.  
  229.  
  230.    srand(time(0));
  231.  
  232. /* The below loop puts blank characters in the input array */
  233.    
  234.    
  235.    for( word=0; word < 8; word++)
  236.    {
  237.       for(position=0 ; position<18 ; position++)
  238.       {
  239.          inputraw[word][position] = '\0'; /* Loading the array with NULL characters seems to reduces errors in matching the input to betlibary */
  240.       }
  241.      
  242.    }
  243.  
  244. /* Calling the loadlibary function copies all the infomation about all the valid bets into the betlibary structure */
  245.  
  246.    loadlibary();
  247.  
  248. /* ### Reading the inputs and separating into inputraw array ### */   
  249.    
  250.    for(word=0;word<8;word+=2)
  251.    {  /* Scanning as pairs of numbers is more compact and easier to read than 1arge scanf statment */
  252.    
  253.       scanf("%s %s ", inputraw[word], inputraw[word+1]);
  254.  
  255.    }
  256.    
  257. /* ### Converting to uppercase ### */
  258.  
  259.    for(word=0;word<8;word+=2)
  260.    {
  261.    
  262.       for(position=0; position<strlen(inputraw[word]); position++)
  263.       {
  264.      
  265.          if( isalpha( inputraw[word][position] ) )
  266.          {
  267.          
  268.             inputraw[word][position] = toupper(inputraw[word][position]);
  269.          
  270.          }
  271.      
  272.       }
  273.    }
  274.  
  275. /* ### Bet detection ### */
  276.  
  277.    for(word=0; word < 8;word += 2) /* Only check the even numbered input words */
  278.    {
  279.      
  280.       for(betnum = 0;betnum<numofbets;betnum++) /* Check the entered word against every valid bet, going over the end of the array causes problems */
  281.       {
  282.          if(strcmp(inputraw[word],betlibary[betnum].name)==0) /* strcmp returns 0 if the strings match */
  283.          {
  284.             bet[(word/2)]=betnum; /* Store the number of the bet they placed */
  285.             break; /* There is no need to continue checking if the bet has matched */
  286.          }
  287.       }
  288.      
  289.       if(bet[(word/2)] == -1) /* If the input didn't match any of the valid bets */
  290.       {
  291.          printf("Invalid bet detected, please enter 4 valid bets\n");
  292.          error++;       
  293.          break;
  294.       }
  295.    
  296.    }
  297.    
  298. /* ### Converting to intergers ### */
  299.  
  300.    for(word = 1, position = 0; word < 8 && error == 0; word += 2 ){
  301.       
  302.       for(position = 0; position<strlen(inputraw[word]);position++)
  303.       {
  304.          if( (isdigit(inputraw[word][position])==0) || (position==0 && (inputraw[word][position]=='0') ) ) /* The part of the IF condition prevents any string starting 0 being valid bet amounts */
  305.          {
  306.             printf("\nInvalid amount bet, please enter 4 whole numbers\n");
  307.             error++;
  308.             break;
  309.          }
  310.          
  311.       }
  312.    
  313.       if( error == 0 ){ /* Only convert to intergers if all the characters are digits*/
  314.          amountbet[((word - 1)/2)] = atoi( inputraw[word] ); /* Convert word 1 to 0, word 3 to 1, etc  */
  315.       }
  316.      
  317.       if( amountbet[((word - 1)/2)] == 0 ){ /* This check is nessesary to catch if the last bet amount is not inputted, and potentially some other error conditions */
  318.          printf("\nInvalid amount bet, please enter 4 whole numbers\n");
  319.          error++;
  320.          break;
  321.       }
  322.       
  323.    }
  324.    
  325. /* ### Spinning the wheel and checking if player has won ### */
  326.    
  327.    if( error == 0 ) /* Only spin the wheel if all the inputs are valid */
  328.    {
  329.       int subtotal = 0;
  330.       for(i=0; i<4 ;i++)
  331.       {
  332.          
  333.          wheel[i] = (rand() %38); /* Save all the random numbers so they can be rendered */
  334.    
  335.          for(j=0; j < betlibary[bet[i]].numofnums;j++) /* The array is not of fixed size so only go upto the number of numbers (numofnums) */
  336.          {
  337.             if(betlibary[bet[i]].numbers[j]==wheel[i]) /* Check every number that the bet can win on */
  338.             {
  339.                amountwon[i] = (amountbet[i] + (amountbet[i]*(betlibary[bet[i]].odds)));
  340.            
  341.                subtotal += (amountwon[i] - amountbet[i]);
  342.            
  343.                sprintf(outputtext[(i*2)],"Ball %d landed on %s, you bet on %s and won!\0",(i+1),betlibary[wheel[i]].name,betlibary[bet[i]].name);
  344.                sprintf(outputtext[(i*2)+1],"You bet %d and thus won %d this is a %d profit, your current subtotal is %d.\0",amountbet[i],amountwon[i],(amountwon[i] - amountbet[i]), subtotal);
  345.          
  346.                error = 0; /* Reset error as the ball has landed on a winning number */
  347.  
  348.                break;
  349.                
  350.             }else
  351.             {
  352.                error = 1; /* If the ball hasn't landed on the betting number then  */
  353.             }
  354.            
  355.           }
  356.          
  357.          if(error == 1) /* if the ball didn't land on any winning number for this bet */
  358.          {
  359.             amountwon[i]= 0;
  360.            
  361.             subtotal = subtotal - amountbet[i];
  362.            
  363.             sprintf(outputtext[(i*2)],"Ball %d landed on %s, you bet on %s and didn't win.\0",(i+1),betlibary[wheel[i]].name,betlibary[bet[i]].name);
  364.             sprintf(outputtext[(i*2)+1],"You bet %d and thus lost %d, your current subtotal is %d.\0",amountbet[i],amountbet[i], subtotal);
  365.          
  366.             error = 0; /* reset error for next time */
  367.          
  368.          }
  369.          
  370.       }
  371.       int totalbet = amountbet[0] + amountbet[1] + amountbet[2] + amountbet[3];
  372.       int totalwon = amountwon[0] + amountwon[1] + amountwon[2] + amountwon[3];
  373.       
  374.       sprintf(outputtext[8],"You bet a total of %d, you won a total of %d!\0",totalbet,totalwon);
  375.       sprintf(outputtext[9],"Your total profit was %d\0",subtotal); /* At the end of all bets print totals */
  376.       
  377.       FILE *animatedGIF;
  378.       gdImagePtr frame;
  379.      
  380.       graphics( wheel, frame, animatedGIF ); /* Render the graphics */
  381.    
  382.    }
  383.    else /* If there were errors */
  384.    {
  385.       
  386.     /* Tell the user how to input a valid input */
  387.        
  388.        printf("\nPlease input 4 bets and 4 bet amounts, separated by a space, for example:");
  389.        printf("\n \"1 100 2 100 3 100 4 100\" \n");
  390.        printf("\nPlease only enter whole numbers for the bet amount \n");
  391.        printf("\nThe valid bets available are:");
  392.        printf("\n    Any single number 0 to 36 and 00");
  393.        printf("\n    Any pair of numbers that are touching in this format: \"1-2\" ");
  394.        printf("\n    Any row of numbers in this format: \"1-2-3\" ");
  395.        printf("\n    Any four numbers that are touching in corners this format: \"1-2-4-5\" ");
  396.        printf("\n    Any six numbers that are touching in this format: \"1-2-3-4-5-6\" ");
  397.        printf("\n    The three columns in this format: \"1stCol\" etc ");
  398.        printf("\n    The three dozens in this format: \"1stDozen\" etc ");
  399.        printf("\n    And single word bets such as:");
  400.        printf("\n      Red, Black, Odd, Even, High, Low \n \n");
  401.        
  402.    
  403.    }
  404.  
  405.    return(0);
  406.  
  407. }
  408.  
  409. void loadbet(int bet, char *name, int odds, int numofnums, int x, int y) /* This function copies the given data into the betlibary struct array */
  410. {
  411.       
  412.    strcpy(betlibary[bet].name, name); /* Copy the name */
  413.    
  414.    betlibary[bet].odds = odds; /* Save the odds */
  415.    
  416.    betlibary[bet].numofnums = numofnums; /* Save the number of numbers that this bet wins on */
  417.    
  418.    betlibary[bet].numbers = malloc(numofnums * sizeof(int)); /* This creates an array of size "numofnums" at the position pointed to by the "numbers" pointer */
  419.    
  420.    for(int i=0;i<numofnums;i++){ /* Copy all the numbers up to the end of the array */
  421.       
  422.       betlibary[bet].numbers[i]=tempnumbers[i]; /* From the tempnumbers array */
  423.      
  424.    }
  425.    
  426.    betlibary[bet].coords[0] = x;
  427.    betlibary[bet].coords[1] = y;
  428.    
  429. }
  430.  
  431. void graphics( int ballnumber[4], int *frame, FILE *animatedGIF ) /* This function renders all the graphics, it should only be used if there are no errors, and the output text is prepared */
  432. {
  433.    /* roulettewheel array contains the the numbers to be put on the wheel in order */
  434.    char roulettewheel[38][4] = {"6","21","33","16","4","23","35","14","2","0","28","9","26","30","11","7","20","32","17","5","22","34","15","3","24","36","13","1","00","27","10","25","29","12","8","19","31","18"};
  435.    
  436.    /* letterangle array contains the angles that the numbers will need to be rotated to have the bottom of the numbers point towards the middle of the circle */
  437.    int letterangle[38] = {267.00,257.53,248.06,238.59,229.12,219.65,210.18,200.71,191.24,181.77,172.30,162.83,153.36,143.89,134.42,124.95,115.48,106.01,96.54,87.07,77.60,68.13,58.66,49.19,39.72,30.25,20.78,11.31,0,355.37,345.90,336.43,326.96,317.49,308.02,298.55,289.08,279.61};
  438.    
  439.    /* positionangle array contains the angle from 3 'o' clock that the letters will be drawn on the wheel */
  440.    int positionangle[38] = {4.0,12.,20.5,29.5,41.0,48.5,58.5,67.5,79.0,88.50,95.0,107.5,115.0,124.0,133.5,145.5,152.5,162.5,172.0,183.50,190.5,200.0,210.0,222.0,229.5,239.5,248.5,259.5,268.5,277.75,286.5,297.5,306.0,315.0,326.5,335.0,344.0,353.0};
  441.  
  442.    /* position array contains the number of segments from 3 'o' clock that the number is in on the wheel */
  443.    int position[38]={9,27,8,23,4,19,0,15,34,11,30,14,33,26,7,22,3,18,37,35,16,1,20,5,24,31,12,29,10,32,13,36,17,2,21,6,25,28};
  444.    
  445.    int framenum,grey,red, black, white,green,radius,blue, j = 0;
  446.    int mybox[8] = {0}; /* the mybox array that is used to hold the coordinates of the corners of the letters after they are rendered */     
  447.    double i = 0,tempangle;
  448.    char temp[4];
  449.    double angle[4] = {0}; /* This array will contain the angle that each ball is currently at */
  450.    
  451.    for( int k =0; k<4;k++) /* This loop looks up the starting position for the balls, based on the angle of the number marking the number position */
  452.    {
  453.       angle[k] = positionangle[position[ballnumber[k]]] -87; /* The ball stops ~90 degrees from where it started */
  454.    }
  455.    
  456.    /* Create first background and frame image */ 
  457.    frame = gdImageCreate( framewidth, frameheight );
  458.    gdImageColorAllocate( frame, 255, 255, 255 );
  459.  
  460.    /* Initialize animated GIF with the first background frame */
  461.    animatedGIF = fopen( "animation.gif", "wb" );
  462.    gdImageGifAnimBegin( frame, animatedGIF, 1, 0 );
  463.  
  464.    /* Start the frame counter at 1 so that it can be used later for movement calculations */ 
  465.    for( framenum = 1; framenum <= maxframecount; framenum++ )
  466.    {
  467.       gdImageDestroy( frame ); /* Release memory for previous frame image */
  468.       
  469.       frame = gdImageCreate( framewidth, frameheight ); /* Create new frame image */
  470.       
  471.       /* Allocate all the colours, this has to be done for each new frame as the infomation is lost when the previous frame is destroyed */
  472.       gdImageColorAllocate( frame, 255, 255, 255 );
  473.       black = gdImageColorAllocate( frame, 0, 0, 0 );
  474.       red = gdImageColorAllocate( frame, 255, 0, 0 );
  475.       grey = gdImageColorAllocate( frame, 128, 128, 128 );
  476.       white = gdImageColorAllocate( frame, 255, 255, 255 );
  477.       green = gdImageColorAllocate( frame, 0, 255, 0 );
  478.       blue = gdImageColorAllocate( frame, 0, 0, 255 );
  479.      
  480.        
  481.       gdImageFilledEllipse( frame, 150, 150, 259, 259, red ); /* Render the red portions of the wheel */
  482.  
  483.       for(j=0,tempangle = 0;j<20;j++,tempangle += 19)
  484.       { /* gdImageFilledArc can only accept intergers for start and end angle, so the black segments have to be 10 degrees wide, 9 degrees apart to fit the correct number on the wheel  */
  485.          gdImageFilledArc( frame, 150, 150, 260, 260, tempangle, (tempangle+10), black, gdArc);
  486.       }
  487.        
  488.       gdImageFilledArc( frame, 150, 150, 260, 260, 86, 95, green, gdArc); /* Render the 2 green segments for 0 and 00 */
  489.       gdImageFilledArc( frame, 150, 150, 260, 260, 266, 276, green, gdArc);
  490.        
  491.       gdImageFilledEllipse( frame, 150, 150, 180, 180, white ); /* Fill the centre of the wheel with white */
  492.  
  493.       gdImageFilledArc( frame, 150, 150, 220, 220, 0, 360, grey, gdNoFill); /* Draw a line splitting the segments in half */
  494.      
  495.       for(j=0;j<38;j++)
  496.       {
  497.          
  498.          radius = 115;
  499.          
  500.          double x = 150 + (radius * cos(positionangle[j] * (PI / 180) ) );
  501.          double y = 150 + (radius * sin(positionangle[j] * (PI / 180) ) );
  502.          
  503.          /* Render the numbers on the wheel, based on the predetermined and tweaked position angle, and rotated by the predetermined and tweaked letter angle */
  504.          gdImageStringFT( frame, mybox, grey, "Vera.ttf", 10, (letterangle[j]*(PI/180)), x, y, roulettewheel[j]);
  505.       }
  506.          
  507.       /* Draw the 4 balls that changes location based on frame counter */
  508.       if(framenum<30)
  509.       {
  510.          for( j=0;j<4;j++)
  511.          {
  512.             angle[j] += 12; /* all the balls are at different angles so this needs to be done indpendently */
  513.             radius = 124; /* all 4 balls are rendered at the same radius so this only needs to happen once */
  514.            
  515.             double x = 150 + (radius * cos(angle[j] * (PI / 180) ) );
  516.             double y = 150 + (radius * sin(angle[j] * (PI / 180) ) );
  517.             gdImageFilledEllipse( frame, (int)x, (int)y, 15, 15, grey );
  518.                    
  519.             sprintf(temp,"%d",j+1); /* convert j+1 to a string so it can be printed on the current ball */
  520.             gdImageStringFT( frame, mybox, red, "Vera.ttf", 8, 0, (x-3), (y+5), temp);
  521.            
  522.          }
  523.            
  524.       }else
  525.       {
  526.                
  527.          radius = (124 - (2 *i)); /* all 4 balls are rendered at the same radius so this only needs to happen once */
  528.                
  529.          for( j=0;j<4;j++)
  530.          {
  531.             angle[j] += (12-i); /* all the balls are at different angles so this needs to be done indpendently */
  532.            
  533.             double x = 150 + (radius * cos(angle[j] * (PI / 180) ) );
  534.             double y = 150 + (radius * sin(angle[j] * (PI / 180) ) );
  535.             gdImageFilledEllipse( frame, (int)x, (int)y, 15, 15, grey );
  536.                    
  537.             sprintf(temp,"%d",j+1); /* convert j+1 to a string so it can be printed on the current ball */
  538.             gdImageStringFT( frame, mybox, red, "Vera.ttf", 8, 0, (x-3), (y+5), temp);
  539.            
  540.          }
  541.            
  542.          if(i < 12)
  543.          { /* all the balls are slowing down and falling at the same speed so this calculation only needs to be done once a frame */
  544.             i += 0.75;
  545.          }
  546.      }
  547.        
  548.      for(j=0;j<numofoutlines;j++) /* print the number of lines defines at program start, numofoutlines is also the size of outputtext array */
  549.      {
  550.        gdImageStringFT( frame, mybox, black, "Vera.ttf", 10, 0, 305, (50 + (j*25)), outputtext[j]);
  551.      }
  552.        
  553.      /* ### Draw the roulette table ### */
  554.       
  555.      /* Define the edges of the main box */
  556.       int left  = 81;
  557.       int top   = 300;
  558.       int right   = left+(12*40);
  559.       int bottom  = top + (3*65);
  560.       int ymiddle = top + 65;
  561.        
  562.       gdImageFilledRectangle(frame, left, top, right, bottom, red); /* Draw the red background */
  563.       gdImageFilledRectangle(frame, left-40, top, left, bottom, green); /* Draw the left hand box for 0 and 00 */
  564.       gdImageFilledRectangle(frame, left, bottom+60, right, bottom, green); /* Draw the bottom box for some of the word bets */
  565.       gdImageFilledRectangle(frame, right, top, right+40, bottom, green); /* Draw the right box for the 3 column bets */
  566.          
  567.       for( j = 0; j < 4; j++) /* Render (most of) the black squares */
  568.       {
  569.          gdImageFilledRectangle(frame, left, ymiddle, left+40, ymiddle+65, black);
  570.            
  571.          left += 40; /* The next 2 squares are on the same line so left only needs to increase once */
  572.          gdImageFilledRectangle(frame, left, bottom, left+40, bottom-65, black);
  573.          
  574.          gdImageFilledRectangle(frame, left, top+65, left+40, top, black);
  575.            
  576.          left += 40; /* Move to the next row */
  577.          gdImageFilledRectangle(frame, left, ymiddle, left+40, ymiddle+65, black);
  578.          
  579.          left += 40;
  580.       }
  581.       left = 81; /* reset left to original value */
  582.      
  583.       /* Render the odd 2 black squares */
  584.       gdImageFilledRectangle(frame, left+120, bottom , left+160, bottom-65, black);
  585.       gdImageFilledRectangle(frame, left+360, bottom, left+400, bottom-65, black);
  586.        
  587.       /* ### Render the vertical grey lines ### */
  588.      
  589.       gdImageFilledRectangle(frame, (left-40)-1, top, (left-40)+1, bottom, grey);
  590.       /* All the lines are drawn as rectangles that are 2 pixels wide to make them more visable */
  591.      
  592.       for( j = 0; j<14; j++, left += 40)
  593.       {
  594.          if( j%4 == 0 ) /* every 4th line needs to be drawn longer */
  595.          {
  596.             gdImageFilledRectangle(frame, left-1, top, left+1, bottom+60, grey);
  597.          }else
  598.          {
  599.             gdImageFilledRectangle(frame, left-1, top, left+1, bottom, grey);
  600.          }
  601.       }
  602.       left = 81; /* reset left to original value */
  603.          
  604.       gdImageFilledRectangle(frame, (left+80)-1, bottom+60, (left+80)+1, bottom+30, grey);
  605.       gdImageFilledRectangle(frame, (left+240)-1, bottom+60, (left+240)+1, bottom+30, grey);
  606.       gdImageFilledRectangle(frame, (left+400)-1, bottom+60, (left+400)+1, bottom+30, grey);
  607.        
  608.       /* ### Render the horizontal grey lines ### */
  609.       gdImageFilledRectangle(frame, left-40, top+1, right+40, top-1, grey);
  610.       gdImageFilledRectangle(frame, left, (ymiddle+65)+1, right+40, (ymiddle+65)-1, grey);
  611.       gdImageFilledRectangle(frame, left, ymiddle+1, right+40, ymiddle-1, grey);
  612.       gdImageFilledRectangle(frame, left-40, bottom+1, right+40, bottom-1, grey);
  613.       
  614.       gdImageFilledRectangle(frame, left-40, (top+97)+1, left, (top+97)-1, grey);
  615.        
  616.       gdImageFilledRectangle(frame, left, (bottom+60)+1, right, (bottom+60)-1, grey);
  617.       gdImageFilledRectangle(frame, left, (bottom+30)+1, right, (bottom+30)-1, grey);
  618.        
  619.       /* ### Render all the numbers on the centre squares ### */
  620.       for(int level =0, shift =0, j=1; j<37;j++)
  621.       {
  622.          sprintf(temp,"%d",j); /* convert j to a string to be printed */
  623.            
  624.          if(j>9) /* If the number is 2 digits it needs a small offset to stay centred */
  625.          {
  626.             shift = 8; /* This is the case as all the text is rendered from the bottom left corner of the first letter */
  627.          }
  628.            
  629.          switch((j-1)%3) /* There is 3 columns of numbers, so doing %3 allows the switch to sort the numbers into the 3 columns, the multiples of 3 are always on the right handed end, so this switch starts */
  630.          { /* the minus 1 is required as j starts at 1 rather than 0 */
  631.             case 0: /* as I did (j-1)%3, case 0 actually starts a 1, then 4, 7, etc */
  632.                gdImageStringFT( frame, mybox, white, "Vera.ttf", 18, (90)*(PI / 180), 110+(level*40), (bottom-25)+shift, temp);
  633.                break;
  634.             case 1:
  635.                gdImageStringFT( frame, mybox, white, "Vera.ttf", 18, (90)*(PI / 180), 110+(level*40), (bottom-90)+shift, temp);
  636.                break;
  637.             case 2: /* This is the actually multiples of 3 */
  638.                gdImageStringFT( frame, mybox, white, "Vera.ttf", 18, (90)*(PI / 180), 110+(level*40), (bottom-155)+shift, temp);
  639.                level++; /* On the last number in this row, move to the next row */
  640.                break;
  641.          }
  642.      }
  643.          
  644.      gdImageStringFT( frame, mybox, black, "Vera.ttf", 20, (90)*(PI / 180), left-10, bottom-40, "0");
  645.      gdImageStringFT( frame, mybox, black, "Vera.ttf", 20, (90)*(PI / 180), left-10, top + 66, "00");
  646.          
  647.      gdImageStringFT( frame, mybox, black, "Vera.ttf", 12, (90)*(PI / 180), right+30, bottom-5, "1stCol");
  648.      gdImageStringFT( frame, mybox, black, "Vera.ttf", 12, (90)*(PI / 180), right+30, bottom-70, "2ndCol");
  649.      gdImageStringFT( frame, mybox, black, "Vera.ttf", 12, (90)*(PI / 180), right+30, bottom-135, "3rdCol");
  650.        
  651.      gdImageStringFT( frame, mybox, black, "Vera.ttf", 12, 0, left+40, bottom+20, "1stDozen");
  652.      gdImageStringFT( frame, mybox, black, "Vera.ttf", 12, 0, left+200,bottom+20, "2ndDozen");
  653.      gdImageStringFT( frame, mybox, black, "Vera.ttf", 12, 0, left+360,bottom+20, "3rdDozen");
  654.          
  655.      gdImageStringFT( frame, mybox, black, "Vera.ttf", 12, 0, left+20, bottom+50, "High");
  656.      gdImageStringFT( frame, mybox, black, "Vera.ttf", 12, 0, left+100, bottom+50, "Even");
  657.      gdImageStringFT( frame, mybox, black, "Vera.ttf", 12, 0, left+180, bottom+50, "Black");
  658.      gdImageStringFT( frame, mybox, black, "Vera.ttf", 12, 0, left+260,bottom+50, "Red");
  659.      gdImageStringFT( frame, mybox, black, "Vera.ttf", 12, 0, left+340,bottom+50, "Odd");
  660.      gdImageStringFT( frame, mybox, black, "Vera.ttf", 12, 0, left+420,bottom+50, "Low");
  661.      
  662.      for(j=0;j<4;j++) /* Draw the 4 chips on the table */
  663.      {
  664.        gdImageFilledEllipse( frame, betlibary[bet[j]].coords[0], betlibary[bet[j]].coords[1], 15, 15, blue );
  665.                    
  666.          sprintf(temp,"%d",j+1); /* convert j+1 to a string so it can be printed on the current chip */
  667.          gdImageStringFT( frame, mybox, white, "Vera.ttf", 8, 0, (betlibary[bet[j]].coords[0]-3), (betlibary[bet[j]].coords[1]+5), temp);
  668.      }
  669.          
  670.      /* Add the frame to the animated gif file */
  671.       gdImageGifAnimAdd( frame, animatedGIF, 1, 0, 0, frametime, 1, NULL );
  672.    }
  673.  
  674.    /* Save the animated gif and clear memory associated with the animation */
  675.    gdImageGifAnimEnd( animatedGIF );
  676.    fclose( animatedGIF );
  677.    gdImageDestroy( frame );
  678.    
  679. }
  680.  
  681. void loadlibary( void )
  682. {
  683.  
  684.    char name[18];
  685.    int i,j,betnum, x, y, level = 0;
  686.    
  687.    int left  = 81;
  688.    int top   = 300;
  689.    int right   = left+(12*40);
  690.    int bottom  = top + (3*65);
  691.    int ymiddle = top + 65;
  692.  
  693.    /* This loop defines all the single number bets */
  694.    for(i=0;i<37;i++)
  695.    { /* ################## really? ############### this loop goes upto 37 as it includes 00 */
  696.       tempnumbers[0] = i;
  697.       sprintf(&name,"%d",i);
  698.      
  699.       if(i != 0) /* 0 is a special case as it is not in the main box */
  700.       {
  701.         switch((i-1)%3) /* There is 3 columns of numbers, so doing %3 allows the switch to sort the numbers into the 3 columns, the multiples of 3 are always on the right handed end */
  702.            {
  703.               case 0: /* as I did (j-1)%3, case 0 actually starts at the multiplies of 3 + 1 */
  704.                  x = 100+(level*40);
  705.                  y = bottom-10;
  706.                  break;
  707.               case 1:
  708.                  x = 100+(level*40);
  709.                  y = bottom-75;
  710.                  break;
  711.               case 2: /* This is the actually multiples of 3 */
  712.                  x = 100+(level*40);
  713.                  y = bottom-140;
  714.                  level++; /* On the last number in this row, move to the next row */
  715.                  break;
  716.            }
  717.       }else
  718.       {
  719.          x = left-20;
  720.          y = bottom-30;
  721.       }
  722.       
  723.       loadbet(i,name,35,1,x,y); /* load the bet into the struct using the loadbet function */
  724.    }
  725.    loadbet(37,"00",35,1,left-20,top+80); /* It is simpiler to define 00 outside the loop, as 00 = 0 in interger form */
  726.    
  727.    /* These lines define the EVEN and ODD bets */
  728.    
  729.    tempnumbers[0]=2, tempnumbers[1]=4, tempnumbers[2]=6, tempnumbers[3]=8, tempnumbers[4]=10, tempnumbers[5]=12, tempnumbers[6]=14, tempnumbers[7]=16, tempnumbers[8]=18, tempnumbers[9]=20, tempnumbers[10]=22, tempnumbers[11]=24, tempnumbers[12]=26, tempnumbers[13]=28, tempnumbers[14]=30, tempnumbers[15]=32, tempnumbers[16]=34, tempnumbers[17]=36;
  730.    loadbet(38,"EVEN",1,18,left+90,bottom+43);
  731.    
  732.    tempnumbers[0]=1, tempnumbers[1]=3, tempnumbers[2]=5, tempnumbers[3]=7, tempnumbers[4]=9, tempnumbers[5]=11, tempnumbers[6]=13, tempnumbers[7]=15, tempnumbers[8]=17, tempnumbers[9]=19, tempnumbers[10]=21, tempnumbers[11]=23, tempnumbers[12]=25, tempnumbers[13]=27, tempnumbers[14]=29, tempnumbers[15]=31, tempnumbers[16]=33, tempnumbers[17]=35;
  733.    loadbet(39,"ODD",1,18,left+330,bottom+43);
  734.    
  735.    /* These lines define the 3 dozens */
  736.    
  737.    tempnumbers[0]=1, tempnumbers[1]=2, tempnumbers[2]=3, tempnumbers[3]=4, tempnumbers[4]=5, tempnumbers[5]=6, tempnumbers[6]=7, tempnumbers[7]=8, tempnumbers[8]=9, tempnumbers[9]=10, tempnumbers[10]=11, tempnumbers[11]=12;
  738.    loadbet(40,"1STDOZEN",2,12,left+20,bottom+14);
  739.    
  740.    tempnumbers[0]=13, tempnumbers[1]=14, tempnumbers[2]=15, tempnumbers[3]=16, tempnumbers[4]=17, tempnumbers[5]=18, tempnumbers[6]=19, tempnumbers[7]=20, tempnumbers[8]=21, tempnumbers[9]=22, tempnumbers[10]=23, tempnumbers[11]=24;
  741.    loadbet(41,"2NDDOZEN",2,12,left+180,bottom+14);
  742.  
  743.    tempnumbers[0]=25, tempnumbers[1]=26, tempnumbers[2]=27, tempnumbers[3]=28, tempnumbers[4]=29, tempnumbers[5]=30, tempnumbers[6]=31, tempnumbers[7]=32, tempnumbers[8]=33, tempnumbers[9]=34, tempnumbers[10]=35, tempnumbers[11]=36;
  744.    loadbet(42,"3RDDOZEN",2,12,left+340,bottom+14);
  745.    
  746.    /* These lines define the 3 columns */
  747.    
  748.    tempnumbers[0]=1, tempnumbers[1]=4, tempnumbers[2]=7, tempnumbers[3]=10, tempnumbers[4]=13, tempnumbers[5]=16, tempnumbers[6]=19, tempnumbers[7]=22, tempnumbers[8]=25, tempnumbers[9]=28, tempnumbers[10]=31, tempnumbers[11]=34;
  749.    loadbet(43,"1STCOL",2,12,right+8,bottom-35);
  750.  
  751.    tempnumbers[0]=2, tempnumbers[1]=5, tempnumbers[2]=8, tempnumbers[3]=11, tempnumbers[4]=14, tempnumbers[5]=17, tempnumbers[6]=20, tempnumbers[7]=23, tempnumbers[8]=26, tempnumbers[9]=29, tempnumbers[10]=32, tempnumbers[11]=35;
  752.    loadbet(44,"2NDCOL",2,12,right+8,bottom-100);
  753.    
  754.    tempnumbers[0]=3, tempnumbers[1]=6, tempnumbers[2]=9, tempnumbers[3]=12, tempnumbers[4]=15, tempnumbers[5]=18, tempnumbers[6]=21, tempnumbers[7]=24, tempnumbers[8]=27, tempnumbers[9]=30, tempnumbers[10]=33, tempnumbers[11]=36;
  755.    loadbet(45,"3RDCOL",2,12,right+8,bottom-165);
  756.    
  757.    /* These lines define the Red and Black bets */
  758.    
  759.    tempnumbers[0]=1, tempnumbers[1]=3, tempnumbers[2]=5, tempnumbers[3]=7, tempnumbers[4]=9, tempnumbers[5]=12, tempnumbers[6]=14, tempnumbers[7]=16, tempnumbers[8]=18, tempnumbers[9]=19, tempnumbers[10]=21, tempnumbers[11]=23, tempnumbers[12]=25, tempnumbers[13]=27, tempnumbers[14]=30, tempnumbers[15]=32, tempnumbers[16]=34, tempnumbers[17]=36;
  760.    loadbet(46,"RED",1,18,left+250,bottom+43);
  761.    
  762.    tempnumbers[0]=2, tempnumbers[1]=4, tempnumbers[2]=6, tempnumbers[3]=8, tempnumbers[4]=10, tempnumbers[5]=11, tempnumbers[6]=13, tempnumbers[7]=15, tempnumbers[8]=17, tempnumbers[9]=20, tempnumbers[10]=22, tempnumbers[11]=24, tempnumbers[12]=26, tempnumbers[13]=28, tempnumbers[14]=29, tempnumbers[15]=31, tempnumbers[16]=33, tempnumbers[17]=35;
  763.    loadbet(47,"BLACK",1,18,left+170,bottom+43);
  764.    
  765.    /* These lines define the High and Low bets */
  766.    
  767.    tempnumbers[0]=1, tempnumbers[1]=2, tempnumbers[2]=3, tempnumbers[3]=4, tempnumbers[4]=5, tempnumbers[5]=6, tempnumbers[6]=7, tempnumbers[7]=8, tempnumbers[8]=9, tempnumbers[9]=10, tempnumbers[10]=11, tempnumbers[11]=12, tempnumbers[12]=13, tempnumbers[13]=14, tempnumbers[14]=15, tempnumbers[15]=16, tempnumbers[16]=17, tempnumbers[17]=18;
  768.    loadbet(48,"LOW",1,18,left+410,bottom+43);
  769.    
  770.    tempnumbers[0]=19, tempnumbers[1]=20, tempnumbers[2]=21, tempnumbers[3]=22, tempnumbers[4]=23, tempnumbers[5]=24, tempnumbers[6]=25, tempnumbers[7]=26, tempnumbers[8]=27, tempnumbers[9]=28, tempnumbers[10]=29, tempnumbers[11]=30, tempnumbers[12]=31, tempnumbers[13]=32, tempnumbers[14]=33, tempnumbers[15]=34, tempnumbers[16]=35, tempnumbers[17]=36;
  771.    loadbet(49,"HIGH",1,18,left+10,bottom+43);
  772.  
  773.     /* The below loop defines the double bets */
  774.    
  775.    for(i=1,betnum=50,level=0; i<34;i++,betnum++)
  776.    {
  777.      
  778.        /* Defines the pair below the number, which can't be done on the last row (ie 34-35-36) hence the for loop stoping at 33 */
  779.          tempnumbers[0]=i;
  780.          tempnumbers[1]=i+3;
  781.        
  782.          switch((i-1)%3) /* There is 3 columns of numbers, so doing %3 allows the switch to sort the numbers into the 3 columns, the multiples of 3 are always on the right handed end */
  783.          {
  784.               case 0: /* as I did (i-1)%3, case 0 actually starts at the multiplies of 3 + 1 */
  785.                  x = 120+(level*40);
  786.                  y = bottom-33;
  787.                  
  788.                  sprintf(&name,"%d-%d",i,i+3);
  789.                  loadbet(betnum,name,17,2,x,y);
  790.                  betnum++; /* betnumber needs to be increased to prevent overwriting the just defined bet */
  791.                  
  792.                  x = 100+(level*40);
  793.                  y = bottom-65;
  794.                  
  795.                  tempnumbers[0]=i;
  796.                  tempnumbers[1]=i+1;
  797.                  sprintf(&name,"%d-%d",i,i+1);
  798.                  loadbet(betnum,name,17,2,x,y);
  799.                  break;
  800.              
  801.               case 1:
  802.                  x = 120+(level*40);
  803.                  y = bottom-98;
  804.                  
  805.                  sprintf(&name,"%d-%d",i,i+3);               
  806.                  loadbet(betnum,name,17,2,x,y);
  807.                  betnum++; /* betnumber needs to be increased to prevent overwriting the just defined bet */
  808.                  
  809.                  x = 100+(level*40);
  810.                  y = bottom-130;
  811.                  
  812.                  tempnumbers[0]=i;
  813.                  tempnumbers[1]=i+1;
  814.                  sprintf(&name,"%d-%d",i,i+1);
  815.                  loadbet(betnum,name,17,2,x,y);
  816.                  
  817.                  break;
  818.               case 2: /* This is the actually multiples of 3 */
  819.                  x = 120+(level*40);
  820.                  y = bottom-163;
  821.                  
  822.                  level++; /* On the last number in this row, move to the next row */
  823.                  sprintf(&name,"%d-%d",i,i+3);
  824.                  loadbet(betnum,name,17,2,x,y);
  825.                  break;
  826.          }
  827.          
  828.    }
  829.    
  830.    /* I define these two manually as it is more compact than adding a pile of logic to the above loop */
  831.    tempnumbers[0]=34, tempnumbers[1]=35;
  832.    loadbet(105,"34-35",17,2,right-20,bottom-65);
  833.  
  834.    tempnumbers[0]=35, tempnumbers[1]=36;
  835.    loadbet(106,"35-36",17,2,right-20,top+65);
  836.  
  837.   
  838.    /* The below loop defines all the triple bets */
  839.  
  840.    for(i=1,betnum=107;i<36;i+=3,betnum++)
  841.    {
  842.    
  843.       for(j=0;j<3;j++)
  844.       {
  845.          tempnumbers[j]=i+j;
  846.       }
  847.       
  848.       sprintf(&name,"%d-%d-%d",i,i+1,i+2);
  849.      
  850.       loadbet(betnum,name,11,3,(left+20)+(40*((i-1)/3)),top);
  851.    }
  852.  
  853.  
  854.    /* This loop defines all the quad/corner bets */
  855.    
  856.    for(i=1,betnum=119;i<33;i++)
  857.    {
  858.    
  859.       if((i%3)!=0)
  860.       {
  861.          for(j=0;j<4;j++)
  862.          {
  863.          
  864.             if(j<2)
  865.             {
  866.                tempnumbers[j]=i+j;
  867.             }else
  868.             {
  869.                tempnumbers[j]=(i+j+1);
  870.             }
  871.          }
  872.          sprintf(&name,"%d-%d-%d-%d",i,i+1,i+3,i+4);
  873.      
  874.          x=(left+40)+(40*((i-1)/3));
  875.          y = bottom - (i%3)*65;
  876.      
  877.          loadbet(betnum,name,8,4,x,y);
  878.          
  879.          betnum++; /* This is not in the for loop brackets as when i is a multiple of 3 there is not a valid bet to be generated so betnum should not increase */
  880.       }
  881.    
  882.    }
  883.  
  884.    /* This loop defines the six number bets */
  885.    
  886.    for(i=1,betnum=141;i<32;i+=3,betnum++)
  887.    {
  888.    
  889.       
  890.       for(j=0;j<6;j++)
  891.       {
  892.          tempnumbers[j]=i+j;
  893.       }
  894.          sprintf(&name,"%d-%d-%d-%d-%d-%d",i,i+1,i+2,i+3,i+4,i+5);
  895.          
  896.          x = (left+40) + (40*(i/3));
  897.          
  898.          loadbet(betnum,name,5,6,x,top);
  899.    
  900.    }
  901.  
  902. }