diff --git a/README.md b/README.md
index 6abf6df..ba3fd52 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,4 @@
AnnaConnect is a silly little text-based connect 4 game c:
-Supports vt100 escape codes and ncurses for drawing the UI
-
-Stuff still be changing so fast that the code is the documentation,
-but at least it's got good enough comments methinks
+Supports vt100 escape codes and ncurses for drawing the UI
\ No newline at end of file
diff --git a/config.h b/config.h
index a134cab..f1e8451 100644
--- a/config.h
+++ b/config.h
@@ -5,3 +5,5 @@
#define BOARD_HEIGHT 6
#define FIRST_NUMBER 1
+
+#define ARROWS
diff --git a/logic.c b/logic.c
index aa36dff..43e192e 100644
--- a/logic.c
+++ b/logic.c
@@ -17,33 +17,40 @@
* along with this program. If not, see .
*/
#include "logic.h"
-#include "macros.h"
-static column_t heightMask( const rowsint_t a ){
+static inline int top( const int a, const int b ){
+ return a < b ? b : a;
+}
+
+static inline int bottom( const int a, const int b ){
+ return a < b ? a : b;
+}
+
+static inline int heightMask( const int a ){
return ( 1 << a ) - 1;
}
-static column_t safeHeightMask( const rowsint_t a ){
+static inline int safeHeightMask( const int a ){
return a > 0 ? heightMask( a ) : 0;
}
-static column_t bottomHeightMask( const rowsint_t a, const rowsint_t b ){
+static inline int bottomHeightMask( const int a, const int b ){
return safeHeightMask( bottom( a, b ) );
}
-void playMove(
+inline void playMove(
board_t *boardptr,
- const columnsint_t column
+ const int column
){
boardptr->column [ column ] |=
boardptr->player << boardptr->height [ column ];
boardptr->height [ column ]++;
}
-void calcWins(
+inline void calcWins(
wins_t *wins,
const board_t board,
- const columnsint_t column
+ const int column
){
// First the simplest win, the humble tower
// Check for lil towers
@@ -72,7 +79,7 @@ void calcWins(
// Now the rest of the wins
// First connect 2
for(
- columnsint_t i = clipped_subtract( column, 1 );
+ int i = top( column - 1, 0 );
i < bottom( column + 1, board.columns - 1 );
i++
){
@@ -101,7 +108,7 @@ void calcWins(
}
// Then stitch the twos together and count
for(
- columnsint_t i = clipped_subtract( column, 3 );
+ int i = top( column - 3, 0 );
i < bottom( column + 1, board.columns - 3 );
i++
){
diff --git a/logic.h b/logic.h
index 488894c..4123f8a 100644
--- a/logic.h
+++ b/logic.h
@@ -6,11 +6,11 @@
extern void playMove(
board_t *boardptr,
- const columnsint_t column
+ const int column
);
extern void calcWins(
wins_t *wins,
const board_t board,
- const columnsint_t column
+ const int column
);
diff --git a/macros.h b/macros.h
index 20b6cf4..a364109 100644
--- a/macros.h
+++ b/macros.h
@@ -1,9 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#pragma once
-#define top( a, b ) ( a < b ? b : a )
-#define bottom( a, b ) ( a < b ? a : b )
-#define clipped_subtract( a, b ) ( a < b ? 0 : a - b )
-
#define XSTR(s) STR(s)
#define STR(s) #s
diff --git a/makefile b/makefile
index 5d10e86..f08e653 100644
--- a/makefile
+++ b/makefile
@@ -1,46 +1,27 @@
#!/usr/bin/make -f
-
-# Target architecture for compilation
-ARCH = native
-
-# Optimization level
-O = 3
-
-# Flags for the compiler
FLAGS = -std=c23
-FLAGS += -O$(O)
-FLAGS += -march=$(ARCH)
-# Only override gcc default tuning if specified in make command line
-ifneq (, $(TUNE))
- FLAGS += -mtune=$(TUNE)
-endif
+FLAGS += -O3
+FLAGS += -march=native
FLAGS += -pedantic
FLAGS += -Wall
FLAGS += -Wextra
FLAGS += -Werror
-# This flag is because of the compiler otherwise giving too much warning
-#FLAGS += -Wformat-truncation=0
+FLAGS += -Wformat-truncation=0
-# Compile flag for defining GITHASH to put at the end of the version string
GITFLAG = -D'GITHASH=$(shell git rev-parse --short=1 HEAD)'
-# Directories where .o files and excecutables will be placed
OBJDIR = obj
OUTDIR = out
-# The UI to compile for by default using make run
#UI_TARGET = vt100
UI_TARGET = ncurses
-# The URL of the plaintext version of the lisence, for the --license option
LICENSEURL = https://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
-# C compiler
CC = cc
.NOTINTERMEDIATE:
-# Messages to print during different steps in making
MSG_FETCHING = FETCHING:
MSG_LINKING = Linking:
MSG_COMPILING = Compiling C:
@@ -48,57 +29,44 @@ MSG_CLEANING = Cleaning:
MSG_CLEANING_OBJ = Cleaning $(OBJDIR):
MSG_CLEANING_OUT = Cleaning $(OUTDIR):
-# Compile for all UI targets
all: $(addprefix $(OUTDIR)/connect4_,ncurses.elf vt100.elf)
-# Compile and run the default UI target
run: $(OUTDIR)/connect4_$(UI_TARGET).elf
./$<
-# Compile and run with a specific UI target
run_%: $(OUTDIR)/connect4_%.elf
./$<
-# Compile specifically the ncurses version
-# This one's special because it needs -lncursesw
$(OUTDIR)/connect4_ncurses.elf: $(addprefix $(OBJDIR)/,ui_ncurses.o logic.o connect4.o LICENSE.o)
@echo $(MSG_LINKING) $@
@mkdir -p $(@D)
$(CC) $(FLAGS) -lncursesw -o $@ $^
-# Compile the final excecutable for a given UI target
$(OUTDIR)/connect4_%.elf: $(addprefix $(OBJDIR)/,ui_%.o logic.o connect4.o LICENSE.o)
@echo $(MSG_LINKING) $@
@mkdir -p $(@D)
$(CC) $(FLAGS) -o $@ $^
-# Make an object file for the license so it does not all need to be in the code
$(OBJDIR)/LICENSE.o: $(OBJDIR)/LICENSE
@echo $(MSG_LINKING) $@
@mkdir -p $(@D)
cd $(@D); ld -r -b binary -o $(@F) $(^F)
-# Compile the object file of the main code.
-# This one's special because it includes the git hash
$(OBJDIR)/connect4.o: connect4.c
@echo $(MSG_COMPILING) $^
@mkdir -p $(@D)
$(CC) -c $(FLAGS) $(GITFLAG) -o $@ $^
-# Generic object file compile
$(OBJDIR)/%.o: %.c
@echo $(MSG_COMPILING) $^
@mkdir -p $(@D)
$(CC) -c $(FLAGS) -o $@ $^
-# Download the license file in non-markdown form.
-# This is not cleaned as that would be too silly
$(OBJDIR)/LICENSE:
@echo $(MSG_FETCHING) $@
curl $(LICENSEURL) \
| sed -n '/END OF TERMS AND CONDITIONS/q;p' > $(OBJDIR)/LICENSE
-# Remove all compilation output and intermediate files
clean:
@echo $(MSG_CLEANING)
@echo $(MSG_CLEANING_OBJ)
diff --git a/types.h b/types.h
index df3c0a4..f5b3688 100644
--- a/types.h
+++ b/types.h
@@ -5,7 +5,7 @@
#include
#include "config.h"
-// Use fastest available ints unless it's 64 bits because that uses more memory
+// Only use big ints on architectures where it doesn't impact speed
#if INT_FAST16_MAX == INT_FAST64_MAX
typedef int rowsint_t;
typedef unsigned columnsint_t;
diff --git a/ui_ncurses.c b/ui_ncurses.c
index 8da8914..00bf47c 100644
--- a/ui_ncurses.c
+++ b/ui_ncurses.c
@@ -71,7 +71,6 @@ void initBoard( const board_t board ){
keypad(stdscr, TRUE);
nonl();
echo();
- __attribute__((assume(board.columns < 999)));
for( columnsint_t column = 0; column < board.columns; column++ ){
char colnum[4];
snprintf(
@@ -97,10 +96,8 @@ void initBoard( const board_t board ){
}
for( rowsint_t row = 0; row < board.rows; row++ ){
char rownum[4];
- const int intToPrint = board.rows - row + FIRST_NUMBER - 1;
- __attribute__((assume(intToPrint <= 256)));
snprintf(
- rownum, sizeof(rownum), "%2d", intToPrint
+ rownum, sizeof(rownum), "%2d", board.rows - row + FIRST_NUMBER - 1
);
mvaddstr(
BOARD_Y + BOARD_DY * ( row + 1 ),
@@ -214,17 +211,13 @@ columnsint_t askColumn(
const board_t board
){
columnsint_t column = 0;
+#ifdef ARROWS
move( BOARD_Y, BOARD_X );
if( board.player ) addstr( "p1" );
else addstr( "p0" );
refresh();
- for(; board.height[ column ] >= board.rows; ){
- column++;
- if( column == board.columns ){
- getch();
- return QUITCOLUMN;
- }
- }
+ for(; board.height[ column ] >= board.rows; )
+ column += ( column < board.columns - 1 );
for(;;){
int ch = mvgetch(
BOARD_Y + BOARD_DY * ( board.rows - board.height[ column ] ),
@@ -252,6 +245,32 @@ columnsint_t askColumn(
break;
}
}
+#else /* !ARROWS */
+ for(;;){
+ mvaddstr(
+ INPUT_Y,
+ INPUT_X,
+ "Where does player "
+ );
+ if( board.player ) addstr( "1" );
+ else addstr( "0" );
+ addstr( " put the piece? " );
+ clrtoeol();
+ refresh();
+ scanw( " %d", &column );
+ column -= FIRST_NUMBER;
+ move(
+ INPUT_Y + 1,
+ INPUT_X
+ );
+ clrtoeol();
+ if( column >= 0 && column < board.columns )
+ if( board.height [ column ] < board.columns )
+ return column;
+ else addstr( "Pls enter a column that ain't full" );
+ else addstr( "Pls enter a column that exists" );
+ }
+#endif /* ! ARROWS */
}
void exit_ui(void){
diff --git a/ui_vt100.c b/ui_vt100.c
index 03b0a8d..cbf68b4 100644
--- a/ui_vt100.c
+++ b/ui_vt100.c
@@ -65,13 +65,14 @@ void initBoard( const board_t board ){
}
void updateBoard(
+ const wins_t wins,
const board_t board,
const columnsint_t column
){
rowsint_t height = board.height [ column ];
printf(
"\033[%dA\033[%dC%c\033[%dB",
- height + 2,
+ height + 3,
column * 3 + 4,
'0' + !!( board.player ),
height + 1
@@ -84,11 +85,11 @@ void updateBoard(
"" WININT_FORMAT " │" WININT_FORMAT "\033[2B\033[8D"
"" WININT_FORMAT " │" WININT_FORMAT "\033[2B"
,( 3 * board.columns + 6 ) + SCOREBOARD_WIDTH - 8
- ,board.count0.vertical, board.count1.vertical
- ,board.count0.horizontal, board.count1.horizontal
- ,board.count0.diagonalUp, board.count1.diagonalUp
- ,board.count0.diagonalDown, board.count1.diagonalDown
- ,board.count0.total, board.count1.total
+ ,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
);
printf( "\033[2K\n" );
}
@@ -111,10 +112,9 @@ columnsint_t askColumn(
if( column < FIRST_NUMBER ) return QUITCOLUMN;
column -= FIRST_NUMBER;
if( column < board.columns )
- if( board.height [ column ] < board.rows ){
- printf( "\033[A" );
+ if( board.height [ column ] < board.rows )
return column;
- } else printf( "\033[2Apls enter a column that ain't full" );
+ else printf( "\033[2Apls enter a column that ain't full" );
else
printf( "\033[2Apls enter valid column" );
printf( "\033[K\n" );