diff --git a/connect4.c b/connect4.c
index 86e89a7..1e52873 100644
--- a/connect4.c
+++ b/connect4.c
@@ -17,6 +17,7 @@
* along with this program. If not, see .
*/
#include
+#include
#include
#include
#include "macros.h"
@@ -25,7 +26,7 @@
#include "types.h"
#include "ui.h"
-#define VERSION 0.0.5
+#define VERSION 0.1.0
#define VERSIONSTRING \
"AnnaConnect version "XSTR(VERSION)", Copyright (C) Anna Snoeijs\n"
@@ -36,19 +37,37 @@ extern char _binary_LICENSE_start[];
extern char _binary_LICENSE_end[];
int main( int argc, char *argv[] ){
+ // Initialise variables
+ wins_t wins = {
+ .count0 = {
+ .total = 0,
+ .vertical = 0,
+ .horizontal = 0,
+ .diagonalUp = 0,
+ .diagonalDown = 0,
+ },
+ };
+ wins.count1 = wins.count0;
+ board_t playboard = {
+ .player = 0,
+ .rows = BOARD_HEIGHT,
+ .columns = BOARD_WIDTH
+ };
// Parse options
for(;;){
// Allowed options
static struct option long_options[] = {
- { "help", no_argument, NULL, 'h' },
- { "license", no_argument, NULL, 'l' },
- { "version", no_argument, NULL, '\0' },
+ { "help", no_argument, NULL, 'h' },
+ { "license", no_argument, NULL, 'l' },
+ { "version", no_argument, NULL, '\0' },
+ { "columns", required_argument, NULL, 'c' },
+ { "rows", required_argument, NULL, 'r' },
{ 0 }
};
// Index of current option
int option_index = 0;
// Get next option
- char c = getopt_long( argc, argv, "hl", long_options, &option_index );
+ char c = getopt_long( argc, argv, "hlc:r:", long_options, &option_index );
if( c == -1 ) break;
// Handle option
switch( c ){
@@ -86,6 +105,12 @@ int main( int argc, char *argv[] ){
putchar( *p );
}
return 0;
+ case 'c': // --columns
+ playboard.columns = atoi(optarg);
+ break;
+ case 'r': // --rows
+ playboard.rows = atoi(optarg);
+ break;
}
}
// Check for unhandled options
@@ -95,6 +120,14 @@ int main( int argc, char *argv[] ){
printf( "%s ", argv[optind++] );
putchar( '\n' );
}
+ if( playboard.rows < 1 ){
+ fprintf( stderr, "ERR: AMOUT OF ROWS MUST BE AT LEAST 1\n" );
+ return -1;
+ }
+ if( playboard.rows >= 32 ){
+ fprintf( stderr, "ERR: AMOUT OF ROWS MUST BE LESS THAN 32\n" );
+ return -1;
+ }
// Start the actual program
printf(
VERSIONSTRING
@@ -103,30 +136,19 @@ int main( int argc, char *argv[] ){
"under certain condtions. See `%s --license`\n", argv[0]
);
// board, innit?
- initBoard();
- board_t playboard = {
- .player = 0,
- .column = {0},
- .height = {0},
- };
- wins_t wins = {
- .count0 = {
- .total = 0,
- .vertical = 0,
- .horizontal = 0,
- .diagonalUp = 0,
- .diagonalDown = 0,
- },
- .count1 = {
- .total = 0,
- .vertical = 0,
- .horizontal = 0,
- .diagonalUp = 0,
- .diagonalDown = 0,
- },
- .win0 = {0},
- .win1 = {0},
- };
+ playboard.height = calloc( playboard.columns, sizeof(int) );
+ playboard.column = calloc( playboard.columns, sizeof(int) );
+ wins.win0 = calloc( playboard.columns, sizeof(int) );
+ wins.win1 = calloc( playboard.columns, sizeof(int) );
+ wins.same.vertical2 = calloc( playboard.columns, sizeof(int) );
+ wins.same.horizontal2 = calloc( playboard.columns, sizeof(int) );
+ wins.same.diagonalUp2 = calloc( playboard.columns, sizeof(int) );
+ wins.same.diagonalDown2 = calloc( playboard.columns, sizeof(int) );
+ wins.same.vertical4 = calloc( playboard.columns, sizeof(int) );
+ wins.same.horizontal4 = calloc( playboard.columns, sizeof(int) );
+ wins.same.diagonalUp4 = calloc( playboard.columns, sizeof(int) );
+ wins.same.diagonalDown4 = calloc( playboard.columns, sizeof(int) );
+ initBoard( playboard );
// Begin loopin
for(;; playboard.player = !playboard.player ){
move_t move = askMove();
diff --git a/logic.c b/logic.c
index 969e9c2..21a251f 100644
--- a/logic.c
+++ b/logic.c
@@ -62,7 +62,7 @@ void calcWins(
// First the simplest win, the humble tower
wins->count0.vertical = 0;
wins->count1.vertical = 0;
- for( int i = 0; i < BOARD_WIDTH; i++ ){
+ for( int i = 0; i < board.columns; i++ ){
// Check for lil towers
wins->same.vertical2 [ i ] =
~( board.column [ i ]
@@ -89,7 +89,7 @@ void calcWins(
wins->count0.diagonalDown = 0;
wins->count1.diagonalDown = 0;
// First connect 2
- for( int i = 0; i < BOARD_WIDTH - 1; i++ ){
+ for( int i = 0; i < board.columns - 1; i++ ){
wins->same.horizontal2 [ i ] =
~( board.column [ i ]
^ board.column [ i + 1 ] )
@@ -114,7 +114,7 @@ void calcWins(
& ~1; // A diagonal line down ain't starts at the floor innit?
}
// Then stitch the twos together and count
- for( int i = 0; i < BOARD_WIDTH - 3; i++ ){
+ for( int i = 0; i < board.columns - 3; i++ ){
wins->same.horizontal4 [ i ] =
wins->same.horizontal2 [ i ]
& wins->same.horizontal2 [ i + 1 ]
diff --git a/types.h b/types.h
index 5ddc194..54d2d7b 100644
--- a/types.h
+++ b/types.h
@@ -1,6 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#pragma once
+#include
#include "config.h"
typedef enum {
@@ -10,19 +11,21 @@ typedef enum {
typedef struct {
int player;
- int height [ BOARD_WIDTH ];
- int column [ BOARD_WIDTH ];
+ int *height;
+ int *column;
+ uint8_t rows;
+ uint8_t columns;
} board_t;
typedef struct {
- int vertical2 [ BOARD_WIDTH ];
- int horizontal2 [ BOARD_WIDTH - 1 ];
- int diagonalUp2 [ BOARD_WIDTH - 1 ];
- int diagonalDown2 [ BOARD_WIDTH - 1 ];
- int vertical4 [ BOARD_WIDTH ];
- int horizontal4 [ BOARD_WIDTH - 3 ];
- int diagonalUp4 [ BOARD_WIDTH - 3 ];
- int diagonalDown4 [ BOARD_WIDTH - 3 ];
+ int *vertical2;
+ int *horizontal2;
+ int *diagonalUp2;
+ int *diagonalDown2;
+ int *vertical4;
+ int *horizontal4;
+ int *diagonalUp4;
+ int *diagonalDown4;
} directions_t;
typedef struct {
@@ -36,7 +39,7 @@ typedef struct {
typedef struct {
wincount_t count0;
wincount_t count1;
- int win0 [ BOARD_WIDTH ];
- int win1 [ BOARD_WIDTH ];
+ int *win0;
+ int *win1;
directions_t same;
} wins_t;
diff --git a/ui.h b/ui.h
index 0fbbacd..18a1673 100644
--- a/ui.h
+++ b/ui.h
@@ -4,7 +4,9 @@
#include "types.h"
#include "config.h"
-extern void initBoard( void );
+extern void initBoard(
+ const board_t board
+);
extern void updateBoard(
const wins_t wins,
diff --git a/ui_ncurses.c b/ui_ncurses.c
index 1d6459c..31d535f 100644
--- a/ui_ncurses.c
+++ b/ui_ncurses.c
@@ -65,13 +65,13 @@
#define SCOREBOARD_HEIGHT 10
#endif
-void initBoard( void ){
+void initBoard( const board_t board ){
setlocale(LC_ALL, "");
initscr();
keypad(stdscr, TRUE);
nonl();
echo();
- for( int column = 0; column < BOARD_WIDTH; column++ ){
+ for( int column = 0; column < board.columns; column++ ){
char colnum[4];
sprintf( colnum, "%2d", column + FIRST_NUMBER );
mvaddstr(
@@ -79,7 +79,7 @@ void initBoard( void ){
BOARD_X + BOARD_DX * ( column + 1 ),
colnum
);
- for(int row = 0; row < BOARD_HEIGHT; row++){
+ for(int row = 0; row < board.rows; row++){
mvaddstr(
BOARD_Y + BOARD_DY * ( row + 1 ),
BOARD_X + BOARD_DX * ( column + 1 ),
@@ -87,14 +87,14 @@ void initBoard( void ){
);
}
mvaddstr(
- BOARD_Y + BOARD_DY * ( BOARD_HEIGHT + 1 ),
+ BOARD_Y + BOARD_DY * ( board.rows + 1 ),
BOARD_X + BOARD_DX * ( column + 1 ),
colnum
);
}
- for(int row = 0; row < BOARD_HEIGHT; row++ ){
+ for(int row = 0; row < board.rows; row++ ){
char rownum[4];
- sprintf( rownum, "%2d", row + FIRST_NUMBER );
+ sprintf( rownum, "%2d", board.rows - row + FIRST_NUMBER - 1 );
mvaddstr(
BOARD_Y + BOARD_DY * ( row + 1 ),
BOARD_X,
@@ -102,7 +102,7 @@ void initBoard( void ){
);
mvaddstr(
BOARD_Y + BOARD_DY * ( row + 1 ),
- BOARD_X + BOARD_DX * ( BOARD_WIDTH + 1 ),
+ BOARD_X + BOARD_DX * ( board.columns + 1 ),
rownum
);
}
@@ -139,7 +139,7 @@ void updateBoard(
switch( move ){
case PUT:
mvaddstr(
- BOARD_Y + BOARD_DY * ( BOARD_HEIGHT - height + 1 ),
+ BOARD_Y + BOARD_DY * ( board.rows - height + 1 ),
BOARD_X + 1 + BOARD_DX * ( column + 1 ),
board.column[ column ] & 1 << ( height - 1 ) ? "1" : "0"
);
@@ -147,7 +147,7 @@ void updateBoard(
default:
for( int row = 0; row < height; row++ ){
mvaddstr(
- BOARD_Y + BOARD_DY * ( BOARD_HEIGHT - row ),
+ BOARD_Y + BOARD_DY * ( board.rows - row ),
BOARD_X + 1 + BOARD_DX * ( column + 1 ),
board.column[ column ] & 1 << row ? "1" : "0"
);
@@ -227,16 +227,16 @@ int askColumn(
if( board.player ) addstr( "p1" );
else addstr( "p0" );
refresh();
- for(; board.height[ column ] >= BOARD_HEIGHT; )
- column += ( column < BOARD_WIDTH - 1 );
+ for(; board.height[ column ] >= board.rows; )
+ column += ( column < board.columns - 1 );
for(;;){
int ch = mvgetch(
- BOARD_Y + BOARD_DY * ( BOARD_HEIGHT - board.height[ column ] ),
+ BOARD_Y + BOARD_DY * ( board.rows - board.height[ column ] ),
BOARD_X + 1 + BOARD_DX * ( column + 1 )
);
switch( ch ){
case KEY_RIGHT:
- column += ( column < BOARD_WIDTH - 1 );
+ column += ( column < board.columns - 1 );
break;
case KEY_LEFT:
column -= ( column > 0 );
@@ -246,9 +246,9 @@ int askColumn(
}
switch( move ){
case PUT:
- for(; board.height[ column ] >= BOARD_HEIGHT; ) switch( ch ){
+ for(; board.height[ column ] >= board.rows; ) switch( ch ){
case KEY_RIGHT:
- if( column >= BOARD_WIDTH ) ch = KEY_LEFT;
+ if( column >= board.columns ) ch = KEY_LEFT;
else column++;
break;
case KEY_LEFT:
@@ -260,7 +260,7 @@ int askColumn(
case POP:
for(; board.height[ column ] <= 0; ) switch( ch ){
case KEY_RIGHT:
- if( column >= BOARD_WIDTH ) ch = KEY_LEFT;
+ if( column >= board.columns ) ch = KEY_LEFT;
else column++;
break;
case KEY_LEFT:
@@ -296,10 +296,10 @@ int askColumn(
INPUT_X
);
clrtoeol();
- if( column >= 0 && column < BOARD_WIDTH )
+ if( column >= 0 && column < board.columns )
switch( move ){
case PUT:
- if( board.height [ column ] < BOARD_HEIGHT )
+ if( board.height [ column ] < board.columns )
return column;
else addstr( "Pls enter a column that ain't full" );
break;
diff --git a/ui_vt100.c b/ui_vt100.c
index d817730..2a54a15 100644
--- a/ui_vt100.c
+++ b/ui_vt100.c
@@ -21,22 +21,22 @@
#include
#include "macros.h"
-#define BOARD_WIDTH_CHARS ( 3 * BOARD_WIDTH + 6 )
+#define BOARD_WIDTH_CHARS ( 3 * board.columns + 6 )
#define SCOREBOARD_OFFSET 5
#define SCOREBOARD_WIDTH 27
#define SCOREBOARD_HEIGHT 9
-void initBoard( void ){
- for( int i = SCOREBOARD_HEIGHT - ( BOARD_HEIGHT + 2 ); i > 0; i-- )
+void initBoard( const board_t board ){
+ for( int i = SCOREBOARD_HEIGHT - ( board.rows + 2 ); i > 0; i-- )
putchar( '\n' );
printf( "\n " );
- for( int column = 0; column < BOARD_WIDTH; column++ )
+ for( int column = 0; column < board.columns; column++ )
printf( "%2d ", column + FIRST_NUMBER );
putchar( '\n' );
- for( int row = BOARD_HEIGHT - 1; row > -1; row-- ){
+ for( int row = board.rows - 1; row > -1; row-- ){
// begin row
printf( "%2d " , row + FIRST_NUMBER );
- for( int column = 0; column < BOARD_WIDTH; column++ )
+ for( int column = 0; column < board.columns; column++ )
printf( "[ ]" );
// end of row
printf( "%2d" , row + FIRST_NUMBER );
@@ -46,7 +46,7 @@ void initBoard( void ){
}
// end of board
printf( " " );
- for( int column = 0; column < BOARD_WIDTH; column++ )
+ for( int column = 0; column < board.columns; column++ )
printf( "%2d ", column + FIRST_NUMBER );
#define SCOREBOARD_LINE_END "\033[B\033["XSTR(SCOREBOARD_WIDTH)"D"
printf("\033["XSTR(SCOREBOARD_OFFSET)"C\033["XSTR(SCOREBOARD_HEIGHT)"A"
@@ -85,7 +85,7 @@ void updateBoard(
break;
default: // Print all the pieces in the column and the air above
printf( "\033[%dA", height + 4 );
- if( height < BOARD_HEIGHT ) printf( "\033[%dC ", column * 3 + 4 );
+ if( height < board.rows ) printf( "\033[%dC ", column * 3 + 4 );
else printf( "\033[%dC", column * 3 + 5 );
for( int row = height; row --> 0; )
printf(
@@ -101,7 +101,7 @@ void updateBoard(
"%3d │%3d\033[B\033[8D"
"%3d │%3d\033[2B\033[8D"
"%3d │%3d\033[2B"
- ,BOARD_WIDTH_CHARS + SCOREBOARD_WIDTH - 8
+ ,( 3 * board.columns + 6 ) + SCOREBOARD_WIDTH - 8
,wins.count0.vertical, wins.count1.vertical
,wins.count0.horizontal, wins.count1.horizontal
,wins.count0.diagonalUp, wins.count1.diagonalUp
@@ -138,10 +138,10 @@ int askColumn(
}
}
column -= FIRST_NUMBER;
- if( column >= 0 && column < BOARD_WIDTH )
+ if( column >= 0 && column < board.columns )
switch( move ){
case PUT:
- if( board.height [ column ] < BOARD_HEIGHT )
+ if( board.height [ column ] < board.rows )
return column;
else printf( "\033[2Apls enter a column that ain't full" );
break;