From 642459a19c6bdb6c54069973ae85476d2ab7869a Mon Sep 17 00:00:00 2001 From: xolatile Date: Sun, 26 Nov 2023 15:11:45 -0500 Subject: [PATCH] Again, minor revision... --- chapter/chapter_2.c | 5 ++++- chapter/chapter_3.c | 23 +++++++++++++---------- chapter/chapter_3.h | 9 ++++++--- chapter/chapter_x.c | 2 +- chapter/chapter_y.c | 2 +- program/program_2.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ program/program_3.c | 7 +++++++ program/program_4.c | 7 +++++++ program/program_5.c | 7 +++++++ program/program_6.c | 7 +++++++ program/program_z.c | 19 +++++++++++++++++++ 11 files changed, 121 insertions(+), 16 deletions(-) create mode 100644 program/program_2.c create mode 100644 program/program_3.c create mode 100644 program/program_4.c create mode 100644 program/program_5.c create mode 100644 program/program_6.c create mode 100644 program/program_z.c diff --git a/chapter/chapter_2.c b/chapter/chapter_2.c index 4b9ea97..9f40d13 100644 --- a/chapter/chapter_2.c +++ b/chapter/chapter_2.c @@ -355,7 +355,7 @@ void curses_synchronize (void) { curses_character = signal; // We need literal value of 'signal' for text input. if (signal == '\033') { // And then we modify the actual 'curses_signal'. - curses_signal |= SIGNAL_ESCAPE; + curses_signal = SIGNAL_ESCAPE; } else if (character_is_digit ((char) signal) != 0) { curses_signal |= SIGNAL_0 + (int) (signal - '0'); } else if (character_is_lowercase ((char) signal) != 0) { @@ -363,6 +363,8 @@ void curses_synchronize (void) { } else if (character_is_uppercase ((char) signal) != 0) { curses_signal |= SIGNAL_A + (int) (signal - 'A'); curses_signal |= SIGNAL_SHIFT; + } else if ((signal == SIGNAL_ARROW_UP) || (signal == SIGNAL_ARROW_DOWN) || (signal == SIGNAL_ARROW_RIGHT) || (signal == SIGNAL_ARROW_LEFT)) { + curses_signal = signal; } else { curses_signal = SIGNAL_NONE; } @@ -370,6 +372,7 @@ void curses_synchronize (void) { for (signal = 0; signal != curses_action_count; ++signal) { // Now, it's time to loop over bound actions. if (curses_signal == curses_activator [signal]) { // If we have a bound signal, then: curses_action [signal] (); // We execute corresponding action (function). + break; } } diff --git a/chapter/chapter_3.c b/chapter/chapter_3.c index 2217f4a..e57e93b 100644 --- a/chapter/chapter_3.c +++ b/chapter/chapter_3.c @@ -35,12 +35,6 @@ can fall-through, like in the example below. Sad truth is, people are dumb, and case(s) in your switch statement. Lets explain what 'echo_one_by_one' function would do. @C -// Print out some stuff, it'll look like this for these inputs (and it'll do nothing for input that isn't between 0 and 3 (inclusive)): -// echo_one_by_one (0) => "Zero One Two Three" -// echo_one_by_one (1) => "One Two Three" -// echo_one_by_one (2) => "Two Three" -// echo_one_by_one (3) => "Three" - static void echo_one_by_one (int number) { switch (number) { case 0: echo ("Zero "); @@ -50,13 +44,18 @@ static void echo_one_by_one (int number) { default: break; } } + +// Print out some stuff, it'll look like this for these inputs (and it'll do nothing for input that isn't between 0 and 3 (inclusive)): +// echo_one_by_one (0) => "Zero One Two Three" +// echo_one_by_one (1) => "One Two Three" +// echo_one_by_one (2) => "Two Three" +// echo_one_by_one (3) => "Three" @ You can find situations in which fall-through cases are good, for example, they can be very useful when encoding some CPU instructions into machine code, but guess what? The compiler will think you've made some kind of mistake, like that you forgot to break from those cases, and it'll warn you about it. I like to clean all compiler warnings (and some -linter warnings, if they're not totally brain-dead), so I just don't use them. I know, sounds stupid, but there's usually some other way to do it, to get the same solution. - -Since we have several methods for printing text, they use standard output (terminal), file descriptor and a string respectively, we could implement them in separate functions, use +linter warnings, if they're not totally brain-dead), so I just don't use them. I know, sounds stupid, but there's usually some other way to do it, to get the same solution. Since +we have several methods for printing text, they use standard output (terminal), file descriptor and a string respectively, we could implement them in separate functions, use function pointers or simply copy+paste bunch of code into lot of functions, and form a "function family". Lets do something very simple and straight forward. We'll end up with repeated code, but sometimes the simplicity can benefit us more than some smart solutions that are harder to understand. I'll explain as we progress... */ @@ -68,7 +67,8 @@ static void to_string (char * data, int size, int file, char * string) { (void) /* Lets break down what's going on here, since it might be confusing for beginners. We've defined 3 internal functions, that'll only be used in this file and no other. They look similar, and they ignore some of their arguments by casting them to 'void', that's how you silence the compiler warnings about unused function agruments. But why are we passing -those arguments if we won't use them? Because we can safely use one function pointer to any of those 3 functions. +those arguments if we won't use them? Because we can safely use one function pointer to any of those 3 functions. Now, before we proceed, variables can hold memory addresses of +other variables, constants and functions. We use that fact now. Internal variable 'printing' is a function pointer to one of those 3 functions, and the default value for it is the memory address of function 'to_output'. So, if we just use it, by default it'll print to standard output. If we call functions below, they'll change the value of 'printing' to coresponding function memory address. I chose to use concatenation @@ -184,6 +184,9 @@ void print (char * format, ...) { va_end (list); // Every variadic function needs to end with this macro... Pun intended. } @ + +Also, needless to say, I don't usually align nor write my programs like this, I did it so you can compare those 3 functions easier. You can see what's changed, what's ignored or +what's same. If you're writing something serious, align it properly, not like this please. */ void print ( char * format, ...) { va_list list; printing = to_output; va_start (list, format); print_select (format, list, 0, NULL); va_end (list); } diff --git a/chapter/chapter_3.h b/chapter/chapter_3.h index 2742918..1842dbb 100644 --- a/chapter/chapter_3.h +++ b/chapter/chapter_3.h @@ -76,14 +76,17 @@ printf ("Heyo world!"); @ Now, don't get scared, C is old language, and I'm aware that this looks like someone made a joke 50 years ago and nobody understood it, they took it serious. In the end, variadic -argument list type 'va_list' is black magic, as well as other 'va_*' stuff. Since 'va_arg' takes only fully promoted types, we're left with types 'int', 'double' and 'char *' -pretty much. Also, keep in mind that you don't need more arguments in 'printf' function, only that "const char * fmt" needs to be there always. It may take some time to get used -to this function, but you can use it for very quick and easy debugging. If you're not sure what value your variables hold at some point, you can just print it there. +argument list type 'va_list' is black magic, as well as other 'va_*' stuff. Since 'va_arg' takes only fully promoted types, we're left with types 'int', 'double', 'void *' and +'char *'. Also, keep in mind that you don't need more arguments in 'printf' function, only that "const char * fmt" needs to be there always. It may take some time to get used to +this function, but you can use it for very quick and easy debugging. If you're not sure what value your variables hold at some point, you can just print it there. I'll show you how to implement variadic argument functions, and we'll use these in few places, but I'm still not a big fan of them. Of course, we won't implement everything that 'printf' function from standard library has, or any more of its' alternatives, just these three below. However, we'll add few small additions, like colouring text with ASCII escape sequences and doing some basic formatting. Once you learn C better, you should take a look at manual pages for functions that you find interesting. Or even better, instead of reading stuff, try to implement them yourself, it's the best approach to learning anything. + +If you wonder why did we cover curses in chapter two, and printing in chapter three, which is simpler and shorter essentially, it's because curses use few "black magic" functions +from header file , while printing uses , which is more difficult to use. We'll use it more in later chapters, but only as a show-case. */ extern void print ( char * format, ...); // Notice the "...", which means it can accept any amount of arguments after that 'format'. diff --git a/chapter/chapter_x.c b/chapter/chapter_x.c index a49f426..d4a214c 100644 --- a/chapter/chapter_x.c +++ b/chapter/chapter_x.c @@ -9,7 +9,7 @@ It is distributed in the hope that it will be useful or harmful, it really depen #ifndef CHAPTER_5_SOURCE #define CHAPTER_5_SOURCE -#include "chapter_5.h" +#include "chapter_x.h" /* So, what are actually getters and setters, and why you should never use them? Lets explain. diff --git a/chapter/chapter_y.c b/chapter/chapter_y.c index 3a643e1..1dd26de 100644 --- a/chapter/chapter_y.c +++ b/chapter/chapter_y.c @@ -9,7 +9,7 @@ It is distributed in the hope that it will be useful or harmful, it really depen #ifndef CHAPTER_6_SOURCE #define CHAPTER_6_SOURCE -#include "chapter_6.h" +#include "chapter_y.h" #define UNUSED(variable) (void) variable diff --git a/program/program_2.c b/program/program_2.c new file mode 100644 index 0000000..c5b7732 --- /dev/null +++ b/program/program_2.c @@ -0,0 +1,49 @@ +/* +Copyright (c) 2023 : Ognjen 'xolatile' Milan Robovic + +Xhartae is free software! You will redistribute it or modify it under the terms of the GNU General Public License by Free Software Foundation. +And when you do redistribute it or modify it, it will use either version 3 of the License, or (at yours truly opinion) any later version. +It is distributed in the hope that it will be useful or harmful, it really depends... But no warranty what so ever, seriously. See GNU/GPLv3. +*/ + +#include "../chapter/chapter_0.c" +#include "../chapter/chapter_1.c" +#include "../chapter/chapter_2.c" + +static int player_x = 0; +static int player_y = 0; + +static void player_move_up (void) { player_y -= 1; limit (& player_y, 0, curses_screen_height - 1); } +static void player_move_down (void) { player_y += 1; limit (& player_y, 0, curses_screen_height - 1); } +static void player_move_left (void) { player_x -= 1; limit (& player_x, 0, curses_screen_width - 1); } +static void player_move_right (void) { player_x += 1; limit (& player_x, 0, curses_screen_width - 1); } + +int main (void) { + terminal_show_cursor (FALSE); + + curses_configure (); +/* + curses_bind (SIGNAL_ARROW_UP, player_move_up); + curses_bind (SIGNAL_ARROW_DOWN, player_move_down); + curses_bind (SIGNAL_ARROW_LEFT, player_move_left); + curses_bind (SIGNAL_ARROW_RIGHT, player_move_right); +*/ + while (curses_active) { + curses_render_background ('.', COLOUR_GREY, EFFECT_BOLD); + curses_render_character ('@', COLOUR_CYAN, EFFECT_BOLD, player_x, player_y); + + switch (curses_character) { + case 'w': player_move_up (); break; + case 'a': player_move_down (); break; + case 's': player_move_left (); break; + case 'd': player_move_right (); break; + default: break; + } + + curses_synchronize (); + } + + terminal_show_cursor (TRUE); + + return (EXIT_SUCCESS); +} diff --git a/program/program_3.c b/program/program_3.c new file mode 100644 index 0000000..b663b3f --- /dev/null +++ b/program/program_3.c @@ -0,0 +1,7 @@ +/* +Copyright (c) 2023 : Ognjen 'xolatile' Milan Robovic + +Xhartae is free software! You will redistribute it or modify it under the terms of the GNU General Public License by Free Software Foundation. +And when you do redistribute it or modify it, it will use either version 3 of the License, or (at yours truly opinion) any later version. +It is distributed in the hope that it will be useful or harmful, it really depends... But no warranty what so ever, seriously. See GNU/GPLv3. +*/ diff --git a/program/program_4.c b/program/program_4.c new file mode 100644 index 0000000..b663b3f --- /dev/null +++ b/program/program_4.c @@ -0,0 +1,7 @@ +/* +Copyright (c) 2023 : Ognjen 'xolatile' Milan Robovic + +Xhartae is free software! You will redistribute it or modify it under the terms of the GNU General Public License by Free Software Foundation. +And when you do redistribute it or modify it, it will use either version 3 of the License, or (at yours truly opinion) any later version. +It is distributed in the hope that it will be useful or harmful, it really depends... But no warranty what so ever, seriously. See GNU/GPLv3. +*/ diff --git a/program/program_5.c b/program/program_5.c new file mode 100644 index 0000000..b663b3f --- /dev/null +++ b/program/program_5.c @@ -0,0 +1,7 @@ +/* +Copyright (c) 2023 : Ognjen 'xolatile' Milan Robovic + +Xhartae is free software! You will redistribute it or modify it under the terms of the GNU General Public License by Free Software Foundation. +And when you do redistribute it or modify it, it will use either version 3 of the License, or (at yours truly opinion) any later version. +It is distributed in the hope that it will be useful or harmful, it really depends... But no warranty what so ever, seriously. See GNU/GPLv3. +*/ diff --git a/program/program_6.c b/program/program_6.c new file mode 100644 index 0000000..b663b3f --- /dev/null +++ b/program/program_6.c @@ -0,0 +1,7 @@ +/* +Copyright (c) 2023 : Ognjen 'xolatile' Milan Robovic + +Xhartae is free software! You will redistribute it or modify it under the terms of the GNU General Public License by Free Software Foundation. +And when you do redistribute it or modify it, it will use either version 3 of the License, or (at yours truly opinion) any later version. +It is distributed in the hope that it will be useful or harmful, it really depends... But no warranty what so ever, seriously. See GNU/GPLv3. +*/ diff --git a/program/program_z.c b/program/program_z.c new file mode 100644 index 0000000..9fb59f1 --- /dev/null +++ b/program/program_z.c @@ -0,0 +1,19 @@ +/* +Copyright (c) 2023 : Ognjen 'xolatile' Milan Robovic + +Xhartae is free software! You will redistribute it or modify it under the terms of the GNU General Public License by Free Software Foundation. +And when you do redistribute it or modify it, it will use either version 3 of the License, or (at yours truly opinion) any later version. +It is distributed in the hope that it will be useful or harmful, it really depends... But no warranty what so ever, seriously. See GNU/GPLv3. +*/ + +#include "../chapter/chapter_0.c" +#include "../chapter/chapter_1.c" +#include "../chapter/chapter_2.c" +#include "../chapter/chapter_x.c" +#include "../chapter/chapter_y.c" + +int main (void) { // EXPERIMENTAL (WILL BE DELETED)... + play_game (); + + return (EXIT_SUCCESS); +}