diff --git a/connect4.c b/connect4.c
index 22c90fc..e2dea63 100644
--- a/connect4.c
+++ b/connect4.c
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* AnnaConnect is a silly little text-based connect 4 game c:
- * Copyright (C) 2024 Anna Snoeijs. anna@snoeijs.tech
+ * Copyright (C) 2025 Anna Snoeijs. anna@snoeijs.tech
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -16,14 +16,32 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
-
#include
+#include
+#include
+#include
+
+#define VERSION 25.01.sid
#define BOARD_WIDTH 7
#define BOARD_HEIGTH 6
#define FIRST_NUMBER 1
+#define INPUT_X 2
+#define INPUT_Y 1
+
+#define SCOREBOARD_X INPUT_X
+#define SCOREBOARD_Y INPUT_Y + 2
+
+#define BOARD_X SCOREBOARD_X + 28
+#define BOARD_Y SCOREBOARD_Y + 1
+
+#define BOARD_DX 3
+#define BOARD_DY 1
+
+#define SCOREBOARD_HEIGTH 10
+
#define XSTR(s) STR(s)
#define STR(s) #s
@@ -89,104 +107,144 @@ static inline int bottomHeigthMask( const int a, const int b ){
return safeHeigthMask( bottom( a, b ) );
}
-#define BOARD_WIDTH_CHARS ( 3 * BOARD_WIDTH + 6 )
-#define SCOREBOARD_OFFSET 5
-#define SCOREBOARD_WIDTH 27
-#define SCOREBOARD_HEIGTH 9
static void initBoard( void ){
- for(int i = SCOREBOARD_HEIGTH - ( BOARD_HEIGTH + 2 ); i > 0; i-- )
- putchar( '\n' );
- printf( "\n " );
- for( int column = 0; column < BOARD_WIDTH; column++ )
- printf( "%2d ", column + FIRST_NUMBER );
- putchar( '\n' );
- for( int row = BOARD_HEIGTH - 1; row > -1; row-- ){
- // begin row
- printf( "%2d " , row + FIRST_NUMBER );
- for( int column = 0; column < BOARD_WIDTH; column++ )
- printf( "[ ]" );
- // end of row
- printf( "%2d" , row + FIRST_NUMBER );
- switch( row ){
+ setlocale(LC_ALL, "");
+ initscr();
+ keypad(stdscr, TRUE);
+ nonl();
+ echo();
+ for( int column = 0; column < BOARD_WIDTH; column++ ){
+ char colnum[4];
+ sprintf( colnum, "%2d", column + FIRST_NUMBER );
+ mvaddstr(
+ BOARD_Y,
+ BOARD_X + BOARD_DX * ( column + 1 ),
+ colnum
+ );
+ for(int row = 0; row < BOARD_HEIGTH; row++){
+ mvaddstr(
+ BOARD_Y + BOARD_DY * ( row + 1 ),
+ BOARD_X + BOARD_DX * ( column + 1 ),
+ "[ ]"
+ );
}
- putchar( '\n' );
+ mvaddstr(
+ BOARD_Y + BOARD_DY * ( BOARD_HEIGTH + 1 ),
+ BOARD_X + BOARD_DX * ( column + 1 ),
+ colnum
+ );
+ }
+ for(int row = 0; row < BOARD_HEIGTH; row++ ){
+ char rownum[4];
+ sprintf( rownum, "%2d", row + FIRST_NUMBER );
+ mvaddstr(
+ BOARD_Y + BOARD_DY * ( row + 1 ),
+ BOARD_X,
+ rownum
+ );
+ mvaddstr(
+ BOARD_Y + BOARD_DY * ( row + 1 ),
+ BOARD_X + BOARD_DX * ( BOARD_WIDTH + 1 ),
+ rownum
+ );
+ }
+ for( int y = 0; y < SCOREBOARD_HEIGTH; y++ ){
+ char *str;
+ switch(y){
+ case 0: str = "┌───────────────┬────┬────┐"; break;
+ case 1: str = "│ player │ 0 │ 1 │"; break;
+ case 2: str = "├───────────────┼────┼────┤"; break;
+ case 3: str = "│ vertical │ │ │"; break;
+ case 4: str = "│ horizontal │ │ │"; break;
+ case 5: str = "│ diagonal up │ │ │"; break;
+ case 6: str = "│ diagonal down │ │ │"; break;
+ case 7: str = "├───────────────┼────┼────┤"; break;
+ case 8: str = "│ total │ │ │"; break;
+ case 9: str = "└───────────────┴────┴────┘"; break;
+ default: str = "The code be brokeys at initboard for the score";
+ }
+ mvaddstr(
+ SCOREBOARD_Y + y,
+ SCOREBOARD_X,
+ str
+ );
}
- // end of board
- printf( " " );
- for( int column = 0; column < BOARD_WIDTH; 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_HEIGTH)"A"
- "┌───────────────┬────┬────┐"SCOREBOARD_LINE_END
- "│ player │ 0 │ 1 │"SCOREBOARD_LINE_END
- "├───────────────┼────┼────┤"SCOREBOARD_LINE_END
- "│ vertical │ │ │"SCOREBOARD_LINE_END
- "│ horizontal │ │ │"SCOREBOARD_LINE_END
- "│ diagonal up │ │ │"SCOREBOARD_LINE_END
- "│ diagonal down │ │ │"SCOREBOARD_LINE_END
- "├───────────────┼────┼────┤"SCOREBOARD_LINE_END
- "│ total │ │ │"SCOREBOARD_LINE_END
- "└───────────────┴────┴────┘"SCOREBOARD_LINE_END
- );
-#undef SCOREBOARD_LINE_END
- putchar( '\n' );
- putchar( '\n' );
}
static void updateBoard(
const wins_t wins,
const board_t board,
-#ifndef ONLYPUT
- const move_t move,
-#endif /* ! ONLYPUT */
const int column
){
- int heigth = board.heigth [ column ];
-#ifndef ONLYPUT
- switch( move ){
- case PUT: // Only print the put one
-#endif /* ! ONLYPUT */
- printf(
- "\033[%dA\033[%dC%c\033[%dB",
- heigth + 3,
- column * 3 + 4,
- '0' + !!( board.player ),
- heigth + 1
- );
-#ifndef ONLYPUT
- break;
- default: // Print all the pieces in the column and the air above
- printf( "\033[%dA", heigth + 4 );
- if( heigth < BOARD_HEIGTH ) printf( "\033[%dC ", column * 3 + 4 );
- else printf( "\033[%dC", column * 3 + 5 );
- for( int row = heigth; row --> 0; )
- printf(
- "\033[B\033[D%c",
- '0' + !!( board.column [ column ] & ( 1 << row ) )
- );
- printf( "\033[2B" );
+ for(int row = 0; row < board.heigth[ column ]; row++){
+ mvaddstr(
+ BOARD_Y + BOARD_DY * ( BOARD_HEIGTH - row ),
+ BOARD_X + 1 + BOARD_DX * ( column + 1 ),
+ board.column[ column ] & 1 << row ? "1" : "0"
+ );
}
-#endif /* ! ONLYPUT */
- printf(
- "\r\033[7A\033[%dC"
- "%3d │%3d\033[B\033[8D"
- "%3d │%3d\033[B\033[8D"
- "%3d │%3d\033[B\033[8D"
- "%3d │%3d\033[2B\033[8D"
- "%3d │%3d\033[2B"
- ,BOARD_WIDTH_CHARS + SCOREBOARD_WIDTH - 8
- ,wins.count0.vertical, wins.count1.vertical
- ,wins.count0.horizontal, wins.count1.horizontal
- ,wins.count0.diagonalUp, wins.count1.diagonalUp
- ,wins.count0.diagonalDown, wins.count1.diagonalDown
- ,wins.count0.total, wins.count1.total
+ char num[4];
+ sprintf( num, "%3d", wins.count0.vertical );
+ mvaddstr(
+ SCOREBOARD_Y + 3,
+ SCOREBOARD_X + 17,
+ num
+ );
+ sprintf( num, "%3d", wins.count1.vertical );
+ mvaddstr(
+ SCOREBOARD_Y + 3,
+ SCOREBOARD_X + 22,
+ num
+ );
+ sprintf( num, "%3d", wins.count0.horizontal );
+ mvaddstr(
+ SCOREBOARD_Y + 4,
+ SCOREBOARD_X + 17,
+ num
+ );
+ sprintf( num, "%3d", wins.count1.horizontal );
+ mvaddstr(
+ SCOREBOARD_Y + 4,
+ SCOREBOARD_X + 22,
+ num
+ );
+ sprintf( num, "%3d", wins.count0.diagonalUp );
+ mvaddstr(
+ SCOREBOARD_Y + 5,
+ SCOREBOARD_X + 17,
+ num
+ );
+ sprintf( num, "%3d", wins.count1.diagonalUp );
+ mvaddstr(
+ SCOREBOARD_Y + 5,
+ SCOREBOARD_X + 22,
+ num
+ );
+ sprintf( num, "%3d", wins.count0.diagonalDown );
+ mvaddstr(
+ SCOREBOARD_Y + 6,
+ SCOREBOARD_X + 17,
+ num
+ );
+ sprintf( num, "%3d", wins.count1.diagonalDown );
+ mvaddstr(
+ SCOREBOARD_Y + 6,
+ SCOREBOARD_X + 22,
+ num
+ );
+ sprintf( num, "%3d", wins.count0.total );
+ mvaddstr(
+ SCOREBOARD_Y + 8,
+ SCOREBOARD_X + 17,
+ num
+ );
+ sprintf( num, "%3d", wins.count1.total );
+ mvaddstr(
+ SCOREBOARD_Y + 8,
+ SCOREBOARD_X + 22,
+ num
);
- printf( "\033[2K\n" );
}
-#undef BOARD_WIDTH_CHARS
-#undef SCOREBOARD_OFFSET
-#undef SCOREBOARD_WIDTH
-#undef SCOREBOARD_HEIGTH
static void playMove(
board_t *boardptr,
@@ -217,39 +275,53 @@ static int askColumn(
,const move_t move
#endif /* ONLYPUT */
){
- int column;
+ int column = 0;
for(;;){
+ mvaddstr(
+ INPUT_Y,
+ INPUT_X,
+ "Where does player "
+ );
+ if( board.player ) addstr( "1" );
+ else addstr( "0" );
#ifndef ONLYPUT
switch( move ){
- case PUT: printf( "Wher player %d put? ", board.player );
- break;
- case POP: printf( "Wher player %d pop? ", board.player );
- }
-#else /* ONLYPUT */
- printf( "Wher player %d put? ", board.player );
+ case PUT:
#endif /* ONLYPUT */
- printf( "\033[K" ); // clear everything after cursor
- scanf( "%d", &column );
+ addstr( " put the piece? " );
+#ifndef ONLYPUT
+ break;
+ case POP:
+ addstr( " pop a piece? " );
+ }
+#endif /* ONLYPUT */
+ clrtoeol();
+ refresh();
+ scanw( " %d", &column );
column -= FIRST_NUMBER;
- if( column >= 0 && column < BOARD_WIDTH )
+ move(
+ INPUT_Y + 1,
+ INPUT_X
+ );
+ clrtoeol();
+ if( column >= 0 && column < BOARD_WIDTH ) // The collumn--; is a really
+ // temporary placeholder to make the unfinished shit compile at least
#ifndef ONLYPUT
switch( move ){
case PUT:
#endif /* ! ONLYPUT */
if( board.heigth [ column ] < BOARD_HEIGTH )
return column;
- else printf( "\033[2Apls enter a column that ain't full" );
+ else addstr( "Pls enter a column that ain't full" );
#ifndef ONLYPUT
break;
case POP:
if( board.heigth [ column ] != 0 )
return column;
- else printf( "\033[2Apls enter a column that ain't empty" );
+ else addstr( "Pls enter a column that ain't empty" );
}
#endif /* ! ONLYPUT */
- else
- printf( "\033[2Apls enter valid column" );
- printf( "\033[K\n" );
+ else addstr( "Pls enter a column that exists" );
}
}
@@ -367,12 +439,13 @@ static void calcWins(
int main(){
// First the boilerplate stuffs
printf(
- "AnnaConnect version 2024, Copyright (C) Anna Snoeijs\n"
+ "AnnaConnect version "XSTR(VERSION)", Copyright (C) Anna Snoeijs\n"
"AnnaConnect comes with ABSOLUTELY NO WARRANTY\n"
"This is free software, and you are welcome to redistribute it\n"
"under certain condtions\n"
);
// board, innit?
+ initBoard();
board_t playboard = {
.player = 0,
.column = {0},
@@ -396,22 +469,16 @@ int main(){
.win0 = {0},
.win1 = {0},
};
+ for(;; playboard.player = !playboard.player ){
#ifndef ONLYPUT
- move_t move = PUT;
-#endif /* ! ONLYPUT */
- initBoard();
- for( int column = 0;; playboard.player = !playboard.player ){
-#ifndef ONLYPUT
- move = askMove();
- column = askColumn( playboard, move );
+ move_t move = askMove();
+ int column = askColumn( playboard, move );
playMove( &playboard, move, column );
- calcWins( &wins, playboard );
- updateBoard( wins, playboard, move, column );
#else /* ONLYPUT */
- column = askColumn( playboard );
+ int column = askColumn( playboard );
playMove( &playboard, column );
+#endif /* ONLYPUT */
calcWins( &wins, playboard );
updateBoard( wins, playboard, column );
-#endif /* ONLYPUT */
}
}
diff --git a/makefile b/makefile
index 2c0c5d5..290e1a6 100644
--- a/makefile
+++ b/makefile
@@ -1,5 +1,5 @@
#!/usr/bin/make -f
-FLAGS = -O3 -pedantic -Wall -Wextra -Werror
+FLAGS = -O3 -pedantic -Wall -Wextra -Werror -lncursesw
AnnaConnect: connect4.c
cc $(FLAGS) -o connect4 connect4.c