adds unicode support

Tue, 18 Sep 2018 15:02:08 +0200

author
Mike Becker <universe@uap-core.de>
date
Tue, 18 Sep 2018 15:02:08 +0200
changeset 69
c8f2c280cff7
parent 68
b34de5ce7d0e
child 70
5427beba96d1

adds unicode support

conf.mk file | annotate | diff | comparison | revisions
src/chess/rules.c file | annotate | diff | comparison | revisions
src/chess/rules.h file | annotate | diff | comparison | revisions
src/game.c file | annotate | diff | comparison | revisions
src/main.c file | annotate | diff | comparison | revisions
src/terminal-chess.h file | annotate | diff | comparison | revisions
--- a/conf.mk	Wed Aug 29 17:31:36 2018 +0200
+++ b/conf.mk	Tue Sep 18 15:02:08 2018 +0200
@@ -32,10 +32,10 @@
 
 BIN        = terminal-chess
 CC         = gcc
-CFLAGS     = -O2 -std=gnu99 `pkg-config --cflags ncurses`
-CFLAGS_D   = -g -std=gnu99 -Wall -pedantic `pkg-config --cflags ncurses`
+CFLAGS     = -O2 -std=gnu99 `pkg-config --cflags ncursesw`
+CFLAGS_D   = -g -std=gnu99 -Wall -pedantic `pkg-config --cflags ncursesw`
 LD         = gcc
-LDFLAGS    = `pkg-config --libs ncurses`
+LDFLAGS    = `pkg-config --libs ncursesw`
 ARFLAGS    = -r
 MKDIRFLAGS = -p
 RMFLAGS    = -f -R
--- a/src/chess/rules.c	Wed Aug 29 17:31:36 2018 +0200
+++ b/src/chess/rules.c	Tue Sep 18 15:02:08 2018 +0200
@@ -204,6 +204,18 @@
     }
 }
 
+unsigned char* getpieceunicode(uint8_t piece) {
+    switch (piece & PIECE_MASK) {
+    case PAWN: return "\u265f";
+    case ROOK: return "\u265c";
+    case KNIGHT: return "\u265e";
+    case BISHOP: return "\u265d";
+    case QUEEN: return "\u265b";
+    case KING: return "\u265a";
+    default: return "";
+    }
+}
+
 uint8_t getpiece(char c) {
     switch (c) {
         case 'R': return ROOK;
--- a/src/chess/rules.h	Wed Aug 29 17:31:36 2018 +0200
+++ b/src/chess/rules.h	Tue Sep 18 15:02:08 2018 +0200
@@ -174,12 +174,23 @@
  * 
  * Does not work for pawns, scince they don't have a character.
  * 
- * @param piece one of ROOK, KNIGHT, BISHOP, QUEEN, KING
+ * @param piece may have color or additional flags
  * @return character value for the specified piece
  */
 char getpiecechr(uint8_t piece);
 
 /**
+ * Maps a piece to a unicode character sequence.
+ * 
+ * The returned unicode is for black pieces.
+ * You may colorize the output by setting the terminal foreground color.
+ * 
+ * @param piece the piece to dispaly
+ * @return unicode character sequence for the specified piece
+ */
+unsigned char* getpieceunicode(uint8_t piece);
+
+/**
  * Checks, if a specified field is covered by a piece of a certain color.
  * 
  * The out-parameters may both be NULL, but if any of them is set, the other
--- a/src/game.c	Wed Aug 29 17:31:36 2018 +0200
+++ b/src/game.c	Tue Sep 18 15:02:08 2018 +0200
@@ -71,7 +71,9 @@
     return 0;
 }
 
-static void draw_board(GameState *gamestate, uint8_t perspective) {
+static void draw_board(GameState *gamestate,
+		       uint8_t perspective,
+		       _Bool unicode) {
     char fen[90];
     compute_fen(fen, gamestate);
     mvaddstr(0, 0, fen);
@@ -80,11 +82,18 @@
         for (uint8_t x = 0 ; x < 8 ; x++) {
             uint8_t col = gamestate->board[y][x] & COLOR_MASK;
             uint8_t piece = gamestate->board[y][x] & PIECE_MASK;
-            char piecec;
+            unsigned char piecestr[5];
             if (piece) {
-                piecec = piece == PAWN ? 'P' : getpiecechr(piece);
+                if (unicode) {
+                    unsigned char* uc = getpieceunicode(piece);
+                    strncpy(piecestr, uc, 5);
+                } else {
+                    piecestr[0] = piece == PAWN ? 'P' : getpiecechr(piece);
+                    piecestr[1] = '\0';
+                }
             } else {
-                piecec = ' ';
+                piecestr[0] = ' ';
+                piecestr[1] = '\0';
             }
             
             _Bool boardblack = (y&1)==(x&1);
@@ -97,9 +106,7 @@
             
             int cy = perspective == WHITE ? boardy-y : boardy-7+y;
             int cx = perspective == WHITE ? boardx+x*3 : boardx+21-x*3;
-            mvaddch(cy, cx, ' ');
-            mvaddch(cy, cx+1, piecec);
-            mvaddch(cy, cx+2, ' ');
+            mvprintw(cy, cx, " %s ", piecestr);
         }
     }
     
@@ -460,9 +467,11 @@
     }
 }
 
-static void post_game(GameState *gamestate, GameInfo *gameinfo) {
+static void post_game(Settings* settings, GameState *gamestate) {
+    GameInfo *gameinfo = &(settings->gameinfo);
+
     move(0,0);
-    draw_board(gamestate, WHITE);
+    draw_board(gamestate, WHITE, settings->unicode);
     
     // TODO: network connection is still open here - think about it!
     
@@ -520,13 +529,13 @@
     _Bool running;
     do {
         clear();
-        draw_board(&gamestate, curcol);
+        draw_board(&gamestate, curcol, settings->unicode);
         running = !domove_singlemachine(&gamestate,
             &(settings->gameinfo), curcol);
         curcol = opponent_color(curcol);
     }  while (running);
     
-    post_game(&gamestate, &(settings->gameinfo));
+    post_game(settings, &gamestate);
 }
 
 void game_continue(Settings *settings, int opponent, GameState *gamestate) {
@@ -541,7 +550,7 @@
     _Bool running;
     do {
         clear();
-        draw_board(gamestate, mycolor);
+        draw_board(gamestate, mycolor, settings->unicode);
         if (myturn) {
             running = !sendmove(gamestate, &(settings->gameinfo),
                 opponent, mycolor);
@@ -551,7 +560,7 @@
         myturn ^= TRUE;
     }  while (running);
     
-    post_game(gamestate, &(settings->gameinfo));
+    post_game(settings, gamestate);
 }
 
 void game_start(Settings *settings, int opponent) {
--- a/src/main.c	Wed Aug 29 17:31:36 2018 +0200
+++ b/src/main.c	Tue Sep 18 15:02:08 2018 +0200
@@ -34,6 +34,7 @@
 #include <string.h>
 #include <time.h>
 #include <getopt.h>
+#include <locale.h>
 
 int get_settings(int argc, char **argv, Settings *settings) {
     char *valid;
@@ -41,7 +42,7 @@
     uint8_t timeunit = 60;
     size_t len;
     
-    for (int opt ; (opt = getopt(argc, argv, "a:bc:hp:rsS:t:v")) != -1 ;) {
+    for (int opt ; (opt = getopt(argc, argv, "a:bc:hp:rsS:t:Uv")) != -1 ;) {
         switch (opt) {
         case 'c':
             settings->continuepgn = optarg;
@@ -58,6 +59,9 @@
         case 'S':
             settings->analyzepgn = optarg;
             break;
+        case 'U':
+            settings->unicode = 0;
+            break;
         case 't':
         case 'a':
             len = strlen(optarg);
@@ -114,6 +118,7 @@
 "  -r            Distribute color randomly\n"
 "  -s            Single machine mode\n"
 "  -t <time>     Specifies time limit (default: no limit)\n"
+"  -U            Disables unicode pieces\n"
 "\nNotes\n"
 "The time unit for -a is seconds and for -t minutes by default. To "
 "specify\nseconds for the -t option, use the s suffix.\n"
@@ -151,6 +156,7 @@
     memset(&settings, 0, sizeof(Settings));
     settings.gameinfo.servercolor = WHITE;
     settings.port = "27015";
+    settings.unicode = !!setlocale(LC_CTYPE, "C.UTF-8");
     return settings;
 }
 
--- a/src/terminal-chess.h	Wed Aug 29 17:31:36 2018 +0200
+++ b/src/terminal-chess.h	Tue Sep 18 15:02:08 2018 +0200
@@ -36,7 +36,7 @@
 #ifndef TERMINAL_CHESS_H
 #define	TERMINAL_CHESS_H
 
-#define PROGRAM_VERSION "0.9-r68"
+#define PROGRAM_VERSION "0.9-r69"
 
 #ifdef	__cplusplus
 extern "C" {
@@ -49,6 +49,7 @@
     char* continuepgn;
     char* analyzepgn;
     _Bool singlemachine;
+    _Bool unicode;
 } Settings;
 
 #define is_server(settings) !((settings)->serverhost)

mercurial