Post your code!

User avatar
Stix
Member
 
Posts: 1379
Joined: Fri Aug 04, 2017 14:19
Location: USA
IRC: nil
In-game: Stix [+alts]

Re: Post your code!

by Stix » Sun Jan 13, 2019 23:13

I edited my previous program to fix some bugs and colorize the health status information.

Example:
High-health = colorize green.
Medium-health = colorize yellow.
Low-health = colorize red.

And here's the updated source-code:
Code: Select all
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define RED   "\x1B[31m"
#define GRN   "\x1B[32m"
#define YEL   "\x1B[33m"
#define RESET "\x1B[0m"

int hunger;
int food;
int thirst;
int water;
int medkit;
int day;
int choice;
int amount;
int turn;
int status;
int status1;
int condition;
int item_value;
int situation;
int health;
int energy;
int attack;
int recover;
int enemy_health;
int enemy_energy;
int enemy_attack;
int enemy_recover;
char death[100];
char item[100];
char situation1[100];
char choice1[100];
char choice2[100];
char choice3[100];
char choice4[100];

int defaults() //stores defaults values that are called at th beginning of the program
{
  status1 = 0;
  status = 0;
  day = 0;
  health = 10;
  hunger = 0;
  thirst = 0;
  food = 5;
  water = 3;
  medkit = 1;
}

int fight_defaults() //stores default values for the functions fight()
{
  enemy_health = 10;
  enemy_energy = 4;
  enemy_attack = 3;
  enemy_recover = 2;
 
  energy = 4;
  attack = 3;
  recover = 2;
}

int drink()
{
  if(water < 1)
    printf("\nYou have no more water to drink.\n");
  else
    if(thirst > 0)
      {
   thirst -= 5;
   water--;
      }
  if(thirst < 0)
    thirst = 0;
}

int eat()
{
  if(food < 1)
    printf("\nYou have no more food to eat.\n");
  else
    if(hunger > 0)
      {
   hunger -= 3;
   food--;
      }
  if(hunger < 0)
    hunger = 0;
}

int do_nothing() //a function that does nothing (hack)
{
  status = status;
}

int heal()
{
  if(medkit < 1)
    printf("\nYou don't have any medkits.\n");
  else 
    if(health < 10)
      {
   printf("\nYou healed.\n");
   health += 3;
   medkit--;
      }
    else
      printf("\nYou are already at full health.\n");
}

int health_bar()
{
  if(condition == 0)
    {
      if(health <= 3)
   printf(RED "\nHealth: %d out of 10"RESET, health);
      if(health > 3)
   {
     if(health < 7)
       printf(YEL "\nHealth: %d out of 10"RESET, health);
   }
      if(health > 6)
   printf(GRN "\nHealth: %d out of 10"RESET, health);
    }
     
  if(condition == 1)
    {
      if(health <= 3)
   printf(RED "\n Health: %d" RESET, health);
      if(health > 3)
   {
     if(health < 7)
       printf(YEL "\n Health: %d" RESET, health);
   }
      if(health > 6)
   printf(GRN "\n Health: %d" RESET, health);
    }
 
  if(condition == 2)
    {
      if(enemy_health <= 3)
   printf(RED "           Health: %d" RESET, enemy_health);
      if(enemy_health > 3)
   {
     if(enemy_health < 7)
       printf(YEL "           Health: %d" RESET, enemy_health);
   }
      if(enemy_health > 6)
   printf(GRN "           Health: %d" RESET, enemy_health);
    }
}
     
int choices() //a function that gives a set of choices based on the current situation
{
  int r2 = rand() % 3;
  int r3 = rand() % 5;
  int r4 = rand() % 2;
 
  if(situation == 1)
    {
      if(choice == 1)
   drink();
      if(choice == 2)
   eat();
      if(choice == 3)
   do_nothing;
      if(choice == 4)
   heal();
      if(choice == 5)
   status = 1;
    }
 
  if(situation == 2)
    {
      switch(choice)
   {
   case 1:
     printf("\nYou started a fight!\n");
     fight();
     break;
   case 2:       
     if(r2 == 2)
       {
         printf("\nYou got attacked by a stranger!\n");
         fight();
       }
     if(r2 <= 1)
       {
         printf("\nYou ran away from a fight.\n");
         do_nothing();
       }
     break;
   case 3:      
     if(r4 == 0)
       break;
     if(r4 == 1)
       printf("\nYou got attacked by a stranger!\n");
     fight();
     break;
   case 4:
     do_nothing();
     break;
   case 5:
     status = 1;
     break;
   }
    }
 
  if(situation == 3)
    {         
      if(r3 == 0)
   {
     strcpy(item, "food-item");
     item_value = 1;
   }
      if(r3 == 1)
   {
     strcpy(item, "water-bottle");
     item_value = 2;
   }
      if(r3 == 2)
   {
     strcpy(item, "medkit");
     item_value = 3;
   } 
      if(r3 >= 3)
   printf("\nThe box was empty!\n");
               
      amount = r3;
   
      if(r3 <= 2)
   {   
     if(choice == 1)
       {
         printf("\nYou found %d %s(s).\n", amount, item);
        
         if(item_value == 1)
      food += amount;
         if(item_value == 2)
      water += amount;
         if(item_value == 3)
      medkit += amount;
       }
   }
     
      if(choice == 2)
   do_nothing();
      if(choice == 3)
   do_nothing();
      if(choice == 4)
   do_nothing();
      if(choice == 5)
   status = 1;
    }
}


int situations() //a function that randomly picks a situation to be current
{
  int r = rand() % 5; //grabbing a random number (0-4)

  if(r <= 2)
    {
      strcpy(situation1, "You are walking through an abandoned town."); //setting situation
      strcpy(choice1, "Drink."); //setting choices for the situation
      strcpy(choice2, "Eat.");
      strcpy(choice3, "Do nothing.");
      strcpy(choice4, "Heal.");
      situation = 1;
    }
 
  if(r == 3)
    {
      strcpy(situation1, "While walking you meet a stranger."); //setting situation
      strcpy(choice1, "Fight."); //setting choices for the situation
      strcpy(choice2, "Run.");
      strcpy(choice3, "Do nothing.");
      strcpy(choice4, " ");
      situation = 2;
    }

  if(r == 4)
    {
      strcpy(situation1, "While walking you find a box."); //setting situation
      strcpy(choice1, "Open it."); //setting choices for the situation
      strcpy(choice2, "Do nothing.");
      strcpy(choice3, " ");
      strcpy(choice4, " ");
      situation = 3;
    }
}

int fight() //a function that handles fighting between the player and enemy ai
{
  fight_defaults();
 
  while(1) //loop repeats until a 'break' is called
    {
      printf("\n>>>>>>>STATS<<<<<<<");
      printf("  >>>>>>>ENEMY<<<<<<<");
      printf("\n*******************");
      printf("  *******************");
      condition = 1;
      health_bar();
      condition = 2;
      health_bar();
      condition = 0;
      printf("\n Energy: %d        ", energy);
      printf("   Energy: %d         ", enemy_energy); 
      printf("\n Attack: %d        ", attack);   
      printf("   Attack: %d         ", enemy_attack);
      printf("\n Recover: %d       ", recover);
      printf("   Recover: %d        ", enemy_recover);
      printf("\n*******************");
      printf("  *******************\n");
     
      turn = 0; //sets turn to players beginning of every loop
     
      if(turn == 0) //takes input if conditions are met
   {
     printf("\nYour turn!\n");
    
     while(turn == 0)
       {
         printf("\n1) Fight.\n2) Recover.\n3) Skip turn.\n");
         scanf("%d", &choice);
        
         if(choice == 1) //calculates the input and makes decisions based on it     
      {
        if(energy >= 1)
          {
            enemy_health += enemy_recover - attack; //attacking enemy
            energy -= 1;
            break; //breaking the loop
          }
        else
          printf("\nYou dont have enough energy to attack!\n");
        continue; //restarting the loop
      }
        
         if(choice == 2)
      energy += recover; //recover energy
         break;
         if(choice == 3)
      do_nothing(); //the if statement executes nothing (hack)
         break;           
       }                      
   }
 
      if(enemy_health < 1) //checking if the player won the fight
   {
     printf("\nYou won the fight!\n");
     break;
   }
     
      death_event();

      if(status1 == 1)
   break;
     
      turn = 1; //sets turn to enemy() function end of every loop
      enemy();
    }
}

int enemy() //a function that takes a number (0-2) and makes decisions based on the result
{
  if(turn == 1)
    {
      printf("\nEnemy's turn!");
      int r = rand() % 3; //grabbing a number (0-2)
     
      switch(r)
   {
   case 0:
     /*fall through (which makes the enemy more likely to attack)*/
   case 1:   
     if(enemy_energy >= 1)
       {
         health += recover - enemy_attack; //attacking player
         enemy_energy -= 1;
         printf("\n\nThe enemy attacked!\n");
         break;
       }
     /*fall through (so the enemy has to recover if they're unable to attack)*/
   case 2:   
     enemy_energy += enemy_recover; //recovering energy
     printf("\n\nThe enemy recovered energy.\n");
     break;
   }
    }


int death_event() //Computes cause of death and prints the death-message accordingly.
{
  if(hunger > 10) //checks if the player has starved
    {
      status = 3;
      strcpy(death, "hunger");
    }
  if(thirst > 10) //checks if the player is dehydrated
    {
      status = 3;
      strcpy(death, "thirst");
    }
  if(health < 1) //checks if the player was killed by the enemy ai
    {
      status = 3;
      strcpy(death, "a stranger");
    }
  if(status == 3)
    {
      /*notifying the user of their characters death*/
      printf("\nDeath by %s, you survived %d days. ", death, day);
      status = 1;
      printf("Press \'1\' to restart or \'2\' to quit: ");
      scanf("%d", &choice);
     
      if(choice == 1)
   {
     status = 2;
     status1 = 1;
   }
     
      if(choice == 2)
   {
     status = 1;
     status1 = 1;
   }
     
      if(choice > 2)
   {    
     /*informing the user of an invalid number for input*/
     printf("\nError: to high a value.\n\n");
     status = 1;
   }
    }
}


int win() //checks if the user wins and notifies them accordingly
{
  if(day > 29)
    printf("\nCongratulations, you survived all %d days!\n\n", day);
}


main()
{
 
  defaults(); //grabbing default values
 
  for(day = 1; day < 31; day++) //a loop that will run until day == 30
    {
      situations(); //executing a function that randomly sets the situation
     
      printf("\nDay %d: %s\n", day, situation1);
      printf("\n>>>>>>>>>>>>>>>>>>STATS<<<<<<<<<<<<<<<<<<");
      printf("\n*****************************************");
      health_bar();
      printf("\nHunger: %d out of 10", hunger);
      printf("\nThirst: %d out of 10", thirst);
      printf("\n\nYou have %d water-bottle(s).", water);
      printf("\nYou have %d food-item(s).", food);
      printf("\nYou have %d medkit(s).", medkit);
      printf("\n*****************************************\n");
      printf("\nShould you:\n1) %s\n2) %s\n3) %s\n4) %s\n", choice1, choice2, choice3, choice4);
     
      scanf("%d", &choice);
     
      /*executing a function that will make decisions based on the current situation and
        the users input*/
      choices();

      if(situation == 1) //incrementing hunger/thirst every loop if the condition is met
   {
     hunger++;
     thirst+=2;
   }

      if(status == 1)
   break;
      if(status == 2)
   defaults(); //grabbing default values
      continue;

      death_event(); //executing a function that checks if the player died
      win(); //executing a function that will check if the user won
     
      if(status == 1)
   break;
      if(status == 2)
   defaults(); //grabbing default values
      continue;
    }

  return(0);
}
Hey, what can i say? I'm the bad guy.
Next release of your favorite game? "Bugfixes" --Wuzzy
[OLD]The new Minetest-offtopic can be found here: https://minetestoftopic.createaforum.com/index.php
 

User avatar
sorcerykid
Member
 
Posts: 1061
Joined: Fri Aug 26, 2016 15:36
Location: Illinois, USA
GitHub: sorcerykid
In-game: Nemo

Re: Post your code!

by sorcerykid » Mon Jan 14, 2019 11:57

I have a habit of going through code and finding astounding amounts of extraneous logic. When it comes to senseless redundancy in programming, I'll admit I'm very anal retentive. Nearly half the mods used on JT2 have been refactored or rewritten from scratch, ultimately culling hundreds of lines. Here's a section of code from Zorman3000's pathfinder API that I recently cleaned up:

I managed to reduce this:
Code: Select all
  local start_x_sign = (start_pos.x - end_pos.x) / math.abs(start_pos.x - end_pos.x)
  local start_z_sign = (start_pos.z - end_pos.z) / math.abs(start_pos.z - end_pos.z)
  local end_x_sign = (end_pos.x - start_pos.x) / math.abs(end_pos.x - start_pos.x)
  local end_z_sign = (end_pos.z - start_pos.z) / math.abs(end_pos.z - start_pos.z)

  -- Correct the signs if they are nan
  if math.abs(start_pos.x - end_pos.x) == 0 then
    start_x_sign = -1
    end_x_sign = 1
  end
  if math.abs(start_pos.z - end_pos.z) == 0 then
    start_z_sign = -1
    end_z_sign = 1
  end


down to only this:
Code: Select all
local base_x_sign = base.pos.x <= goal_pos.x and -1 or 1
local goal_x_sign = -base_x_sign
local base_z_sign = base_pos.z <= goal_pos.z and -1 or 1
local goal_z_sign = -base_z_sign
 

User avatar
Hybrid Dog
Member
 
Posts: 2718
Joined: Thu Nov 01, 2012 12:46

Re: Post your code!

by Hybrid Dog » Sat Jan 19, 2019 14:19

I've written code for nearly spherical lighting.
Minetest default:
Image
Spherical:
Image
I didn't make a 3d version and haven't implemented in minetest yet.
https://github.com/minetest/minetest/is ... -446650534
I don't know the performance impact. It uses vectors instead of scalars for light spreading.
Code: Select all
#include <stdlib.h> // malloc, EXIT_*
#include <string.h> // memset
#include <math.h>
#include <png.h>

#define EXIT_PNG(F) if (!F) { \
   fprintf(stderr, "%s\n", bild.message); \
   return EXIT_FAILURE; \
}

#define CLAMP(V, A, B) (V) < (A) ? (A) : (V) > (B) ? (B) : (V)

#define u8 unsigned char

struct pixel {
   u8 r;
   u8 g;
   u8 b;
   u8 a;
};
#define PIXELBYTES 4

struct matrix {
   int w;
   int h;
   float *data;
};

struct image {
   int w;
   int h;
   struct pixel *pixels;
};

/*! \brief get y, cb and cr values each in [0;1] from u8 r, g and b values
 *
 * there's gamma correction,
 * see http://www.ericbrasseur.org/gamma.html?i=1#Assume_a_gamma_of_2.2
 * 0.5 is added to cb and cr to have them in [0;1]
 */
static void rgb2ycbcr(u8 or, u8 og, u8 ob, float *y, float *cb, float *cr)
{
   float divider = 1.0f / 255.0f;
   float r = powf(or * divider, 2.2f);
   float g = powf(og * divider, 2.2f);
   float b = powf(ob * divider, 2.2f);
   *y = (0.299f * r + 0.587f * g + 0.114f * b);
   *cb = (-0.168736f * r - 0.331264f * g + 0.5f * b) + 0.5f;
   *cr = (0.5f * r - 0.418688f * g - 0.081312f * b) + 0.5f;
}

/*! \brief the inverse of the function above
 *
 * numbers from http://www.equasys.de/colorconversion.html
 * if values are too big or small, they're clamped
 */
static void ycbcr2rgb(float y, float cb, float cr, u8 *r, u8 *g, u8 *b)
{
   float vr = (y + 1.402f * (cr - 0.5f));
   float vg = (y - 0.344136f * (cb - 0.5f) - 0.714136f * (cr - 0.5f));
   float vb = (y + 1.772f * (cb - 0.5f));
   float exponent = 1.0f / 2.2f;
   vr = powf(vr, exponent);
   vg = powf(vg, exponent);
   vb = powf(vb, exponent);
   *r = CLAMP(vr * 255.0f, 0, 255);
   *g = CLAMP(vg * 255.0f, 0, 255);
   *b = CLAMP(vb * 255.0f, 0, 255);
}

/*! \brief Convert an rgba image to 4 ycbcr matrices with values in [0, 1]
 */
static struct matrix *image_to_matrices(struct image *bild)
{
   int w = bild->w;
   int h = bild->h;
   struct matrix *matrices = malloc(
      PIXELBYTES * sizeof(struct matrix));
   for (int i = 0; i < PIXELBYTES; ++i) {
      matrices[i].w = w;
      matrices[i].h = h;
      matrices[i].data = malloc(w * h * sizeof(float));
   }
   for (int i = 0; i < w * h; ++i) {
      struct pixel px = bild->pixels[i];
      // put y, cb, cr and transpatency into the matrices
      rgb2ycbcr(px.r, px.g, px.b,
         &matrices[0].data[i], &matrices[1].data[i], &matrices[2].data[i]);
      float divider = 1.0f / 255.0f;
      matrices[3].data[i] = px.a * divider;
   }
   return matrices;
}

/*! \brief Convert 4 matrices to an rgba image
 *
 * Note that matrices becomes freed.
 */
static struct image *matrices_to_image(struct matrix *matrices)
{
   struct image *bild = malloc(sizeof(struct image));
   int w = matrices[0].w;
   int h = matrices[0].h;
   bild->w = w;
   bild->h = h;
   struct pixel *pixels = malloc(w * h * PIXELBYTES);
   for (int i = 0; i < w * h; ++i) {
      struct pixel *px = &pixels[i];
      ycbcr2rgb(matrices[0].data[i], matrices[1].data[i], matrices[2].data[i],
         &px->r, &px->g, &px->b);
      //~ float a = matrices[3].data[i] * 255;
      //~ px->a = CLAMP(a, 0, 255);
      px->a = 255;
   }
   for (int i = 0; i < PIXELBYTES; ++i) {
      free(matrices[i].data);
   }
   free(matrices);
   bild->pixels = pixels;
   return bild;
}

/*! \brief Here my algorithm resides
 *
 * \param mat The 4 matrices obtained form image_to_matrices.
 * \param s The input parameter.
 */
static void apply_algorithm(struct matrix *mat, int s)
{
   // preparation
   int w = mat->w; // input width
   int h = mat->h;
   float *input = mat->data;
   int w2 = w; // output width
   int h2 = h;
   int input_size = w * h * sizeof(float);
   int output_size = input_size;
   float *d = malloc(output_size);

////////////////////////////////////////////////////////////////////////////////

   // y x offset values:
   // 1 -1, 1 1, -1 1, -1 -1
#define YOFF(V) (1 - ((V) & 2))
#define XOFF(V, YO) ((YO) * ((((V) << 1) & 2) - 1))

   struct light {
      float vals[4];
   };

   // Initialize light map
   int lm_w = w+2;
   int lm_h = h+2;
   struct light lightmap[(lm_h)*lm_w + lm_w];
   memset(lightmap, 0, lm_w * lm_h * sizeof(struct light));

   // Initialize blockage map
   u8 blocked[(lm_h)*lm_w + lm_w];
   memset(lightmap, 0, lm_w * lm_h);
   for (int y = 1; y < h+1; ++y) {
      for (int x = 1; x < w+1; ++x) {
         // Light is blocked where the input image is bright enough
         blocked[y*lm_w + x] = input[y*w + x] > 0.5f;
      }
   }


   // Add start light source in the middle
   struct light source = {{15.0, 15.0, 15.0, 15.0}};
   lightmap[(lm_h/2)*lm_w + lm_w/2] = source;

   // Spread light until nothing changes
   const float sqrt2 = sqrt(2.0);
   int spread_cnt = 5318008;
   while (spread_cnt > 0) {
      spread_cnt = 0;
      for (int y = 1; y < h+1; ++y) {
         for (int x = 1; x < w+1; ++x) {
            struct light *l = &lightmap[y*lm_w + x];
            for (int v = 0; v < 4; ++v) {
               float light = l->vals[v];
               if (light == 0)
                  // No light for this direction
                  continue;

               int y_off = YOFF(v);
               int x_off = XOFF(v, y_off);
               int spread_before = spread_cnt;

               // Propagate horizontally and vertically or the other way
               // round
               float light_neigh = light - 1.0f;
               // Get the vector pointing 90° left to where v points to
               int v_left = (v + 3) % 4;
               int y_off_left = YOFF(v_left);
               int x_off_left = XOFF(v_left, y_off_left);
               // Get the middle between where v and v_left points to,
               // this is the horizontal or vertical neighbour left to
               // the diagonal neighbour from before
               y_off_left = (y_off_left + y_off) / 2;
               x_off_left = (x_off_left + x_off) / 2;
               int i_left = (y+y_off_left)*lm_w + x+x_off_left;
               if (!blocked[i_left]
                     && light_neigh > lightmap[i_left].vals[v]) {
                  // Update the light for the same vector but for the
                  // horizontal or vertical neighbour
                  lightmap[i_left].vals[v] = light_neigh;
                  ++spread_cnt;
               }
               // Analogous for the right one
               int v_right = (v + 1) % 4;
               int y_off_right = YOFF(v_right);
               int x_off_right = XOFF(v_right, y_off_right);
               y_off_right = (y_off_right + y_off) / 2;
               x_off_right = (x_off_right + x_off) / 2;
               int i_right = (y+y_off_right)*lm_w + x+x_off_right;
               if (!blocked[i_right]
                     && light_neigh > lightmap[i_right].vals[v]) {
                  // Update the light for the same vector but for the
                  // horizontal or vertical neighbour
                  lightmap[i_right].vals[v] = light_neigh;
                  ++spread_cnt;
               }

               // Propagate diagonally
               // Do not propagate if left and right were blocked
               int i_diag = (y+y_off)*lm_w + x+x_off;
               float light_diag = light - sqrt2;
               if (!blocked[i_diag] && spread_before < spread_cnt
                     && light_diag > lightmap[i_diag].vals[v]) {
                  // Update the light for the same vector but for the
                  // diagonal neighbour
                  lightmap[i_diag].vals[v] = light_diag;
                  ++spread_cnt;
               }
            }
         }
      }
      fprintf(stderr, "%d lights spread.\n", spread_cnt);
   }

   // Move the light to the picture

   int i = 0;
   for (int y = 0; y < h; ++y) {
      for (int x = 0; x < w; ++x) {
         float light = 0.0;
         struct light *l = &lightmap[(y+1)*lm_w + x+1];
         for (int v = 0; v < 4; ++v) {
            if (light < l->vals[v])
               light = l->vals[v];
         }
         int light_quantized = light + 0.5f;
         d[i++] = light_quantized / 15.0f;
      }
   }

////////////////////////////////////////////////////////////////////////////////

   // update the matrix
   mat->data = d;
   mat->w = w2;
   mat->h = h2;

   // tidy up
   free(input);
}

/*! \brief applies the algorithm on each matrix
 *
 * \param bild The image, it's content is changed when finished.
 * \param s Must be a natural number.
 */
void do_an_image(struct image **bild, int s)
{
   struct matrix *matrices = image_to_matrices(*bild);
   //~ for (int i = 0; i < PIXELBYTES; ++i) {
   for (int i = 0; i < 1; ++i) {
      apply_algorithm(&(matrices[i]), s);
   }
   *bild = matrices_to_image(matrices);
}

int main(int argc, char **args)
{
   if (argc != 2) {
      fprintf(stderr, "Missing arguments, usage: <cmdname> "
         "<input>\n");
      return EXIT_FAILURE;
   }
   int input = atoi(args[1]);
   if (input < 2) {
      fprintf(stderr, "Invalid: %d\n",
         input);
      return EXIT_FAILURE;
   }

   png_image bild;
   memset(&bild, 0, sizeof(bild));
   bild.version = PNG_IMAGE_VERSION;
   EXIT_PNG(png_image_begin_read_from_stdio(&bild, stdin))

   int w = bild.width;
   int h = bild.height;
   bild.flags = PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB;
   bild.format = PNG_FORMAT_RGBA;
   struct pixel *pixels = malloc(w * h * 4);
   EXIT_PNG(png_image_finish_read(&bild, NULL, pixels, 0, NULL))


   struct image origpic = {w = w, h = h, pixels = pixels};
   struct image *newpic = &origpic;
   do_an_image(&newpic, input);
   bild.width = newpic->w;
   bild.height = newpic->h;
   free(pixels);
   pixels = newpic->pixels;
   free(newpic);


   EXIT_PNG(png_image_write_to_stdio(&bild, stdout, 0, pixels, 0, NULL));
   free(pixels); // redundant free to feed valgrind
   return EXIT_SUCCESS;
}

‮‪‮
‮‪‮
‮‪‮
‮‪‮
‮‪‮
‮‪‮
‮‪‮
‮‪‮
‮‪
 

User avatar
sorcerykid
Member
 
Posts: 1061
Joined: Fri Aug 26, 2016 15:36
Location: Illinois, USA
GitHub: sorcerykid
In-game: Nemo

Re: Post your code!

by sorcerykid » Sat Jan 19, 2019 16:30

Nice work HybridDog, I presume lighting calculations are handled server side?

Here's a quick one-liner tcsh alias for creating file backups. The "bak" command will maintain a sequential file history with permissions and timestamps in tact. This can come in useful when editing config files or testing lua scripts, without the need for a full fledged git repository.

Usage is very straightforward:

    % bak minetest 3 conf
In this case "minetest" is the base file name, 3 is the next number in the sequence, and "conf" is the extension. The file named "minetest.conf" will be thus copied using option -ip to "minetest.old3.conf" in the same directory. You will be given a warning if the sequence number already exists, so there's no worry about accidental clobbering.

Just add the following two lines to ~/.tcshrc, and you're ready to go!

Code: Select all
alias bak 'cp -ip \!:1.\!:3 \!:1.bak\!:2.\!:3'
alias old 'cp -ip \!:1.\!:3 \!:1.old\!:2.\!:3'


Of course, with some simple tweaks to the alias, it would also be possible to archive the backups into a subdirectory such as "_old" or even to tarball them. And if you want to get really fancy, you could automate the file numbering as follows:

Code: Select all
set DOLLAR='$'
alias bak '/bin/ls -1v \!:1.bak*.\!:2 | tail -n 1 | awk -F"." "{printf substr(${DOLLAR}2,4)+1}" | xargs -0 -ISEQ cp -ip \!:1.\!:2 \!:1.bakSEQ.\!:2'


Now it's as simple as typing bak minetest conf, to backup the minetest configuration file.

Note that this requires creating an environment variable $DOLLAR, due to the quirky rules about interpolation within double quoted strings.
 

User avatar
joe7575
Member
 
Posts: 310
Joined: Mon Apr 24, 2017 20:38
Location: Germany, in the deep south
GitHub: joe7575
In-game: JoSto

Re: Post your code!

by joe7575 » Sun Jan 20, 2019 11:26

Generate a HTML file with table of contents from 'lua_api.txt':
* install markdown2
* download 'lua_api.txt'
* run the script
Code: Select all
#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-

# first install markdown2 via: pip install markdown2

import markdown2

header = u"""<!doctype html>
    <html>
        <head>
            <title>Lua Modding API Reference - Minetest Modding Book</title>
            <meta charset="UTF-8">
            <meta name="author" content="rubenwardy">
            <style>
                code { background-color:#F0F0F0;}
            </style>
        </head>
    <body>
        <h2>Table of Contents</h2>
""".encode("utf-8")

footer = """
    </body>
</html>""".encode("utf-8")

html = markdown2.markdown_path("./lua_api.txt", extras=["toc"])
toc = html.toc_html.encode("utf-8")
body = html.encode("utf-8")

file("./lua_api.html", "wt").write(header + toc + body + footer)
print "Ready."
Sent from my Commodore 64. My Mods: TechPack, Hyperloop, Tower Crane, Lumberjack, Iron Age, Entrance, Minecart, Signs Bot.
 

User avatar
sorcerykid
Member
 
Posts: 1061
Joined: Fri Aug 26, 2016 15:36
Location: Illinois, USA
GitHub: sorcerykid
In-game: Nemo

Re: Post your code!

by sorcerykid » Mon May 27, 2019 04:11

Here's a string library function that supports conditional pattern matching with capture groups stored to the underscore variable.

Code: Select all
string.is_match = function( text, glob )
     -- use underscore variable to preserve captures
     _ = { string.match( text, glob ) )
     return #_ > 0
end


This is a simple example of how string.is_match() can be used:

Code: Select all
if string.is_match( input, "^load (%w+)$" ) or string.is_match( input, "^load (%w+%.txt)$" ) then
     print( "loading file " .. _[ 1 ] )
     -- code to load file
elseif string.is_match( input, "^save (%w+)$" ) or string.is_match( input, "^save (%w+%.txt)$" ) then
     print( "saving file " .. _[ 1 ] )
     -- code to save file
end
 

User avatar
Gael de Sailly
Member
 
Posts: 731
Joined: Sun Jan 26, 2014 17:01
Location: Lyon, France
GitHub: Gael-de-Sailly
IRC: Gael-de-Sailly
In-game: Gael-de-Sailly Ginkgoo

Re: Post your code!

by Gael de Sailly » Wed May 29, 2019 01:05

Tiny code snippet for CSV file parsing – if anyone need it.
Code: Select all
local function read_csv(path)
   local file = io.open(path, "r")
   local t = {}
   for line in file:lines() do
      if line:sub(1,1) ~= "#" and line:find("[^%,% ]") then
         table.insert(t, line:split(",", true))
      end
   end
   return t
end


Larger piece of code to load binary numbers, including floats, that will be needed for the next version of geo-mapgen.
Code: Select all
numberio = {}

-- Define number types

local ntypes = {
   int8    = {1, false, true},
   uint8   = {1, false, false},
   int16   = {2, false, true},
   uint16  = {2, false, false},
   float16 = {2, true, 5, 10},
   int32   = {4, false, true},
   uint32  = {4, false, false},
   float32 = {4, true, 8, 23},
   int64   = {8, false, true},
   uint64  = {8, false, false},
   float64 = {8, true, 11, 52},
}

for name, ntype in pairs(ntypes) do
   numberio[name] = ntype
end

-- Endianness

local bigendian = false

function numberio.get_endianness()
   return bigendian
end

function numberio.set_endianness(is_bigendian)
   bigendian = is_bigendian
end

local function reverse_table(t)
   local n = #t
   for i=1, math.floor(n/2) do
      t[i], t[n+1-i] = t[n+1-i], t[i]
   end
end

-- READ NUMBERS

local function read_bits(bytes, ...)
   local pattern = {...}
   if not bigendian then
      reverse_table(bytes)
   end
   local r = 8
   local b = table.remove(bytes, 1)
   local v = {}
   for _, nbits in ipairs(pattern) do
      local n = 0
      while nbits > r do
         nbits = nbits - r
         n = n + b*2^nbits
         r = 8
         b = table.remove(bytes, 1)
      end
      if nbits > 0 then
         local d = 2^(r-nbits)
         n = n + math.floor(b/d)
         b = b % d
         r = r - nbits
      end
      table.insert(v, n)
   end

   return unpack(v)
end

local function get_reader(ntype)
   local len, is_float, p1, p2 = unpack(ntype)

   local reader
   if is_float then -- Float
      local exp_offset = -2^(p1-1)+1
      local exp_max = 2^p1-1
      local denormal_factor = 2^(exp_offset+1)
      local mantissa_factor = 2^-p2
      reader = function(input)
         local sign, exp, mantissa = read_bits(input, 1, p1, p2)
         sign = (-1)^sign
         if exp == 0 then
            if mantissa == 0 then
               return sign * 0
            end
            return sign * denormal_factor * mantissa * mantissa_factor
         elseif exp == exp_max then
            if mantissa == 0 then
               return sign*math.huge
            else
               return sign < 0 and math.sqrt(-1) or -math.sqrt(-1)
            end
         end
         return sign * 2^(exp+exp_offset) * (1 + mantissa*mantissa_factor)
      end
   elseif p1 then -- Signed int
      local nbits = len*8
      local max = 2^(nbits-1)
      local decr = 2^nbits
      reader = function(input)
         local n = read_bits(input, nbits)
         if n >= max then
            return n - decr
         end
         return n
      end
   else -- Unsigned int
      local nbits = len*8
      reader = function(input)
         return read_bits(input, nbits)
      end
   end
   ntype.reader = reader
   return reader
end

function numberio.readnumber(input, ntype, pack)
   if type(ntype) == "string" then
      ntype = ntypes[ntype]
   end
   local reader = ntype.reader
   if not reader then
      reader = get_reader(ntype)
   end

   local len = ntype[1]
   local inputlen = math.floor(#input/len)

   if inputlen == 1 then
      local bytes = {input:byte(1, len)}
      if pack then
         return {reader(bytes)}
      else
         return reader(bytes)
      end
   else
      local v = {}
      local start = 1
      for i=1, inputlen do
         local stop = i*len
         local bytes = {input:byte(start, stop)}
         table.insert(v, reader(bytes))
         start = stop + 1
      end

      if pack then
         return v
      else
         return unpack(v)
      end
   end
end
Just realize how bored we would be if the world was perfect.
 

Previous

Return to General Discussion



Who is online

Users browsing this forum: No registered users and 11 guests