Les membres ayant 30 points peuvent parler sur les canaux annonces, projets et hs du chat.
La shoutbox n'est pas chargée par défaut pour des raisons de performances. Cliquez pour charger.

Forum Casio - Autres questions


Index du Forum » Autres questions » Can someone compile a chess AI .g4m for fx-CG100?
Uzi_3026 Hors ligne Membre Points: 2 Défis: 0 Message

Can someone compile a chess AI .g4m for fx-CG100?

Posté le 08/03/2026 04:37

Hi! I have a chess add-in written in C using Gint but I can't get the toolchain working on Windows WSL. Could someone please compile it into a .g4m for fx-CG100?

Here is the main.c source code:

/*
* chess.g4m  –  Chess AI for CASIO fx-CG100 / Graph 90+E / fx-CG50
*
* Built with fxSDK + Gint  (https://gitea.planet-casio.com/Lephenixnoir/gint)
* Compiler : sh-elf-gcc  (SH4A-nofpu, fxSDK toolchain)
*
* Features
*   · Full legal chess (castling, en-passant, promotion, 50-move draw)
*   · AI: minimax + alpha-beta pruning, 3 difficulty levels
*   · Per-side clock
*   · Captured-material score
*   · Last-move & check highlight
*   · Move hints (dots / red border for captures)
*/

#include <gint/gint.h>
#include <gint/display.h>
#include <gint/keyboard.h>
#include <gint/timer.h>
#include <gint/rtc.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>

/* ── Screen dimensions (fx-CG100 QVGA colour screen) ─────────────────────── */
#define SW 384
#define SH 216

/* ── Board pixel layout ───────────────────────────────────────────────────── */
#define BX   14          /* board left edge                                   */
#define BY   12          /* board top edge                                    */
#define CS   24          /* cell size (px)                                    */
#define PANEL_X  (BX + CS*8 + 6)   /* right info panel                       */

/* ── Piece constants ─────────────────────────────────────────────────────── */
#define EMPTY   0
#define PAWN    1
#define KNIGHT  2
#define BISHOP  3
#define ROOK    4
#define QUEEN   5
#define KING    6

/* positive = white, negative = black */
#define P_WHITE(p)  ((p) > 0)
#define P_BLACK(p)  ((p) < 0)
#define P_TYPE(p)   abs(p)
#define P_SIGN(w)   ((w) ? 1 : -1)

/* ── Colours (RGB565) ────────────────────────────────────────────────────── */
#define C_BG        C_RGB(2,  2,  4)
#define C_PANEL     C_RGB(3,  3,  7)
#define C_LIGHT_SQ  C_RGB(30, 27, 22)
#define C_DARK_SQ   C_RGB(22, 17, 12)
#define C_CURSOR    C_RGB(6,  28,  8)
#define C_SELECTED  C_RGB(4,  26,  4)
#define C_HINT      C_RGB(8,  16, 28)
#define C_CAPTURE   C_RGB(28,  8,  8)
#define C_CHECK     C_RGB(31,  4,  4)
#define C_LASTMOVE  C_RGB(26, 22,  6)
#define C_WHITE_P   C_RGB(31, 31, 30)
#define C_BLACK_P   C_RGB(4,   4,  5)
#define C_TEXT      C_RGB(27, 27, 27)
#define C_DIM       C_RGB(14, 14, 18)
#define C_GOLD      C_RGB(31, 25,  4)
#define C_GREEN     C_RGB(8,  28, 12)
#define C_RED       C_RGB(28,  6,  6)
#define C_TITLE     C_RGB(20, 14, 31)
#define C_EASY      C_RGB(8,  26, 14)
#define C_MED       C_RGB(30, 22,  4)
#define C_HARD      C_RGB(28,  8,  8)
#define C_OUTLINE   C_RGB(10, 10, 12)

/* ── Piece values (centipawns) ───────────────────────────────────────────── */
static const int PIECE_VAL[7] = {0, 100, 320, 330, 500, 900, 20000};

/* ── Piece-square tables (white perspective, flipped for black) ─────────── */
static const int PST_PAWN[8][8] = {
    { 0,  0,  0,  0,  0,  0,  0,  0},
    {50, 50, 50, 50, 50, 50, 50, 50},
    {10, 10, 20, 30, 30, 20, 10, 10},
    { 5,  5, 10, 25, 25, 10,  5,  5},
    { 0,  0,  0, 20, 20,  0,  0,  0},
    { 5, -5,-10,  0,  0,-10, -5,  5},
    { 5, 10, 10,-20,-20, 10, 10,  5},
    { 0,  0,  0,  0,  0,  0,  0,  0},
};
static const int PST_KNIGHT[8][8] = {
    {-50,-40,-30,-30,-30,-30,-40,-50},
    {-40,-20,  0,  0,  0,  0,-20,-40},
    {-30,  0, 10, 15, 15, 10,  0,-30},
    {-30,  5, 15, 20, 20, 15,  5,-30},
    {-30,  0, 15, 20, 20, 15,  0,-30},
    {-30,  5, 10, 15, 15, 10,  5,-30},
    {-40,-20,  0,  5,  5,  0,-20,-40},
    {-50,-40,-30,-30,-30,-30,-40,-50},
};
static const int PST_KING[8][8] = {
    {-30,-40,-40,-50,-50,-40,-40,-30},
    {-30,-40,-40,-50,-50,-40,-40,-30},
    {-30,-40,-40,-50,-50,-40,-40,-30},
    {-30,-40,-40,-50,-50,-40,-40,-30},
    {-20,-30,-30,-40,-40,-30,-30,-20},
    {-10,-20,-20,-20,-20,-20,-20,-10},
    { 20, 20,  0,  0,  0,  0, 20, 20},
    { 20, 30, 10,  0,  0, 10, 30, 20},
};

/* ═══════════════════════════════════════════════════════════════════════════
*  BOARD / GAME STATE
* ═══════════════════════════════════════════════════════════════════════════ */
typedef struct {
    int  board[8][8];
    int  ep_r, ep_c;        /* en-passant target square (-1 if none)        */
    int  castle;            /* bitmask: bit0=WK bit1=WQ bit2=BK bit3=BQ    */
    int  white_turn;
    int  half_moves;        /* 50-move rule counter                         */
    int  full_moves;
} Position;

typedef struct {
    int fr, fc, tr, tc;
} Move;

static void pos_init(Position *p) {
    memset(p, 0, sizeof(*p));
    static const int back[8] = {ROOK,KNIGHT,BISHOP,QUEEN,KING,BISHOP,KNIGHT,ROOK};
    for (int c=0;c<8;c++) {
        p->board[0][c] = -back[c];
        p->board[1][c] = -PAWN;
        p->board[6][c] =  PAWN;
        p->board[7][c] =  back[c];
    }
    p->ep_r = -1; p->ep_c = -1;
    p->castle = 0xF;   /* all rights */
    p->white_turn = 1;
    p->full_moves = 1;
}

/* ── Move list ───────────────────────────────────────────────────────────── */
#define MAX_MOVES 256
typedef struct { Move m[MAX_MOVES]; int n; } MoveList;

static inline int inb(int r,int c){ return r>=0&&r<8&&c>=0&&c<8; }

/* ── Check detection ─────────────────────────────────────────────────────── */
static int sq_attacked(const Position *p, int r, int c, int by_white) {
    int s = by_white ? 1 : -1;
    int b[8][8]; memcpy(b, p->board, sizeof(b));

    /* Pawns */
    int d = by_white ? 1 : -1;
    for (int dc=-1;dc<=1;dc+=2)
        if (inb(r+d,c+dc) && b[r+d][c+dc]==s*PAWN) return 1;

    /* Knights */
    static const int kd[8][2]={{-2,-1},{-2,1},{-1,-2},{-1,2},{1,-2},{1,2},{2,-1},{2,1}};
    for (int i=0;i<8;i++) {
        int tr=r+kd[i][0],tc=c+kd[i][1];
        if (inb(tr,tc) && b[tr][tc]==s*KNIGHT) return 1;
    }
    /* Bishops / Queen diagonals */
    static const int dd[4][2]={{-1,-1},{-1,1},{1,-1},{1,1}};
    for (int i=0;i<4;i++) {
        int tr=r+dd[i][0],tc=c+dd[i][1];
        while(inb(tr,tc)){
            if(b[tr][tc]!=EMPTY){
                if(b[tr][tc]==s*BISHOP||b[tr][tc]==s*QUEEN) return 1;
                break;
            }
            tr+=dd[i][0]; tc+=dd[i][1];
        }
    }
    /* Rooks / Queen straights */
    static const int sd[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
    for (int i=0;i<4;i++) {
        int tr=r+sd[i][0],tc=c+sd[i][1];
        while(inb(tr,tc)){
            if(b[tr][tc]!=EMPTY){
                if(b[tr][tc]==s*ROOK||b[tr][tc]==s*QUEEN) return 1;
                break;
            }
            tr+=sd[i][0]; tc+=sd[i][1];
        }
    }
    /* King */
    for (int dr=-1;dr<=1;dr++) for (int dc=-1;dc<=1;dc++) {
        if(!dr&&!dc) continue;
        int tr=r+dr,tc=c+dc;
        if(inb(tr,tc)&&b[tr][tc]==s*KING) return 1;
    }
    return 0;
}

static void find_king(const Position *p, int white, int *kr, int *kc) {
    int t = white ? KING : -KING;
    for (int r=0;r<8;r++) for (int c=0;c<8;c++)
        if(p->board[r][c]==t){ *kr=r; *kc=c; return; }
    *kr=0; *kc=0;
}

static int in_check(const Position *p, int white) {
    int kr,kc; find_king(p,white,&kr,&kc);
    return sq_attacked(p,kr,kc,!white);
}

/* ── Raw move generation ─────────────────────────────────────────────────── */
static void gen_moves_for(const Position *pos, int r, int c, MoveList *ml) {
    int piece = pos->board[r][c];
    if(!piece) return;
    int white = piece>0, pt = abs(piece);

    #define ADD(TR,TC) do{ if(ml->n<MAX_MOVES){ \
        ml->m[ml->n].fr=r; ml->m[ml->n].fc=c; \
        ml->m[ml->n].tr=(TR); ml->m[ml->n].tc=(TC); ml->n++; } }while(0)

    #define STEP(DR,DC) do{ int tr=r+(DR),tc=c+(DC); \
        if(inb(tr,tc)){ int t=pos->board[tr][tc]; \
        if(!t||(t>0)!=white) ADD(tr,tc); } }while(0)

    #define SLIDE(DR,DC) do{ int tr=r+(DR),tc=c+(DC); \
        while(inb(tr,tc)){ int t=pos->board[tr][tc]; \
        if(!t){ ADD(tr,tc); } \
        else{ if((t>0)!=white) ADD(tr,tc); break; } \
        tr+=(DR); tc+=(DC); } }while(0)

    if(pt==PAWN){
        int d=white?-1:1, sr=white?6:1;
        /* forward */
        if(inb(r+d,c)&&!pos->board[r+d][c]){
            ADD(r+d,c);
            if(r==sr&&!pos->board[r+2*d][c]) ADD(r+2*d,c);
        }
        /* captures */
        for(int dc=-1;dc<=1;dc+=2){
            int tr=r+d,tc=c+dc;
            if(!inb(tr,tc)) continue;
            int t=pos->board[tr][tc];
            if(t&&(t>0)!=white) ADD(tr,tc);
            else if(tr==pos->ep_r&&tc==pos->ep_c) ADD(tr,tc);
        }
    } else if(pt==KNIGHT){
        static const int kd[8][2]={{-2,-1},{-2,1},{-1,-2},{-1,2},{1,-2},{1,2},{2,-1},{2,1}};
        for(int i=0;i<8;i++) STEP(kd[i][0],kd[i][1]);
    } else if(pt==BISHOP){
        SLIDE(-1,-1); SLIDE(-1,1); SLIDE(1,-1); SLIDE(1,1);
    } else if(pt==ROOK){
        SLIDE(-1,0); SLIDE(1,0); SLIDE(0,-1); SLIDE(0,1);
    } else if(pt==QUEEN){
        SLIDE(-1,-1); SLIDE(-1,0); SLIDE(-1,1);
        SLIDE( 0,-1);              SLIDE( 0,1);
        SLIDE( 1,-1); SLIDE( 1,0); SLIDE( 1,1);
    } else if(pt==KING){
        for(int dr=-1;dr<=1;dr++) for(int dc=-1;dc<=1;dc++)
            if(dr||dc) STEP(dr,dc);
        /* Castling */
        int row=white?7:0;
        if(r==row&&c==4){
            int km=white?0:2, qm=white?1:3;
            /* Kingside */
            if((pos->castle>>km)&1 &&
               !pos->board[row][5] && !pos->board[row][6] &&
               !sq_attacked(pos,row,4,!white) &&
               !sq_attacked(pos,row,5,!white))
                ADD(row,6);
            /* Queenside */
            if((pos->castle>>qm)&1 &&
               !pos->board[row][3] && !pos->board[row][2] && !pos->board[row][1] &&
               !sq_attacked(pos,row,4,!white) &&
               !sq_attacked(pos,row,3,!white))
                ADD(row,2);
        }
    }
    #undef ADD
    #undef STEP
    #undef SLIDE
}

/* Apply move, return captured piece type (0 if none) */
static int apply_move(Position *pos, Move mv) {
    int fr=mv.fr,fc=mv.fc,tr=mv.tr,tc=mv.tc;
    int piece=pos->board[fr][fc];
    int white=piece>0, pt=abs(piece);
    int captured=abs(pos->board[tr][tc]);

    pos->board[tr][tc]=piece;
    pos->board[fr][fc]=EMPTY;

    /* En passant capture */
    if(pt==PAWN && tr==pos->ep_r && tc==pos->ep_c){
        int cap_r=tr+(white?1:-1);
        captured=PAWN;
        pos->board[cap_r][tc]=EMPTY;
    }
    /* New ep square */
    if(pt==PAWN && abs(tr-fr)==2){
        pos->ep_r=(fr+tr)/2; pos->ep_c=tc;
    } else { pos->ep_r=-1; pos->ep_c=-1; }

    /* Promotion → Queen */
    if(pt==PAWN&&(tr==0||tr==7))
        pos->board[tr][tc]=(white?QUEEN:-QUEEN);

    /* Castling rook */
    if(pt==KING){
        int row=white?7:0;
        if(tc==6&&fc==4){ pos->board[row][5]=pos->board[row][7]; pos->board[row][7]=EMPTY; }
        if(tc==2&&fc==4){ pos->board[row][3]=pos->board[row][0]; pos->board[row][0]=EMPTY; }
        if(white) pos->castle&=~0x3; else pos->castle&=~0xC;
    }
    if(pt==ROOK){
        if(fr==7&&fc==7) pos->castle&=~0x1;
        if(fr==7&&fc==0) pos->castle&=~0x2;
        if(fr==0&&fc==7) pos->castle&=~0x4;
        if(fr==0&&fc==0) pos->castle&=~0x8;
    }

    pos->half_moves = (pt==PAWN||captured) ? 0 : pos->half_moves+1;
    if(!white) pos->full_moves++;
    pos->white_turn=!pos->white_turn;
    return captured;
}

/* Legal move generation (filters out moves leaving king in check) */
static void legal_moves_all(const Position *pos, MoveList *out) {
    out->n=0;
    int white=pos->white_turn;
    for(int r=0;r<8;r++) for(int c=0;c<8;c++){
        int p=pos->board[r][c];
        if(!p||(p>0)!=white) continue;
        MoveList tmp; tmp.n=0;
        gen_moves_for(pos,r,c,&tmp);
        for(int i=0;i<tmp.n;i++){
            Position nb=*pos;
            apply_move(&nb,tmp.m[i]);
            if(!in_check(&nb,white)){
                if(out->n<MAX_MOVES) out->m[out->n++]=tmp.m[i];
            }
        }
    }
}

static void legal_dests_for(const Position *pos, int r, int c, MoveList *out){
    out->n=0;
    int p=pos->board[r][c]; if(!p) return;
    int white=p>0;
    MoveList tmp; tmp.n=0;
    gen_moves_for(pos,r,c,&tmp);
    for(int i=0;i<tmp.n;i++){
        Position nb=*pos;
        apply_move(&nb,tmp.m[i]);
        if(!in_check(&nb,white)){
            if(out->n<MAX_MOVES) out->m[out->n++]=tmp.m[i];
        }
    }
}

/* ═══════════════════════════════════════════════════════════════════════════
*  EVALUATION & AI
* ═══════════════════════════════════════════════════════════════════════════ */
static int evaluate(const Position *pos) {
    int score=0;
    for(int r=0;r<8;r++) for(int c=0;c<8;c++){
        int p=pos->board[r][c]; if(!p) continue;
        int white=p>0, pt=abs(p);
        int v=PIECE_VAL[pt];
        int pr=white?r:7-r;
        if(pt==PAWN)   v+=PST_PAWN[pr][c];
        else if(pt==KNIGHT) v+=PST_KNIGHT[pr][c];
        else if(pt==KING)   v+=PST_KING[pr][c];
        score += white?v:-v;
    }
    return score;
}

/* Move ordering: captures first */
static int move_score(const Position *pos, Move mv){
    int cap=abs(pos->board[mv.tr][mv.tc]);
    int pt=abs(pos->board[mv.fr][mv.fc]);
    return cap?PIECE_VAL[cap]-pt/10:0;
}
static int cmp_moves(const void *a,const void *b){return *(int*)b-*(int*)a;}

static int minimax(const Position *pos, int depth, int alpha, int beta,
                   int maxi, Move *best_out) {
    if(depth==0) return evaluate(pos);
    MoveList ml; legal_moves_all(pos,&ml);
    if(!ml.n){
        if(in_check(pos,pos->white_turn)) return maxi?-90000:90000;
        return 0;
    }
    /* Simple capture-first ordering */
    int scores[MAX_MOVES];
    for(int i=0;i<ml.n;i++) scores[i]=move_score(pos,ml.m[i]);
    /* bubble sort (small lists) */
    for(int i=0;i<ml.n-1;i++) for(int j=i+1;j<ml.n;j++)
        if(scores[j]>scores[i]){
            int ts=scores[i]; scores[i]=scores[j]; scores[j]=ts;
            Move tm=ml.m[i]; ml.m[i]=ml.m[j]; ml.m[j]=tm;
        }

    Move local_best=ml.m[0];
    int best = maxi?-100000:100000;
    for(int i=0;i<ml.n;i++){
        Position nb=*pos;
        apply_move(&nb,ml.m[i]);
        int v=minimax(&nb,depth-1,alpha,beta,!maxi,NULL);
        if(maxi){
            if(v>best){ best=v; local_best=ml.m[i]; }
            if(v>alpha) alpha=v;
        } else {
            if(v<best){ best=v; local_best=ml.m[i]; }
            if(v<beta) beta=v;
        }
        if(beta<=alpha) break;
    }
    if(best_out) *best_out=local_best;
    return best;
}

static const int AI_DEPTH[3]={1,3,4}; /* easy, medium, hard */

/* ═══════════════════════════════════════════════════════════════════════════
*  DRAWING
* ═══════════════════════════════════════════════════════════════════════════ */

/* Gint colour helper: drect fills a rectangle */
static void fill(int x,int y,int w,int h,int c){
    drect(x,y,x+w-1,y+h-1,c);
}

/* Small 5×7 piece bitmaps (1 row per int, bit4=leftmost) */
static const uint8_t GLYPH[7][7]={
    {0},                                                /* EMPTY         */
    {0x0E,0x0E,0x04,0x0E,0x1F,0x1F,0x00},             /* PAWN          */
    {0x0E,0x1E,0x1F,0x0F,0x06,0x1F,0x00},             /* KNIGHT        */
    {0x04,0x0E,0x0E,0x04,0x0E,0x1F,0x00},             /* BISHOP        */
    {0x15,0x1F,0x0E,0x0E,0x0E,0x1F,0x00},             /* ROOK          */
    {0x15,0x15,0x1F,0x0E,0x0E,0x1F,0x00},             /* QUEEN         */
    {0x04,0x1F,0x04,0x0E,0x0E,0x1F,0x00},             /* KING          */
};

static void draw_glyph(int x,int y,int pt,int fg,int bg){
    for(int row=0;row<7;row++){
        uint8_t bits=GLYPH[pt][row];
        for(int col=0;col<5;col++){
            int on=(bits>>(4-col))&1;
            dpixel(x+col,y+row,on?fg:bg);
        }
    }
}

static void draw_border(int x,int y,int w,int h,int c){
    drect(x,y,x+w-1,y,c);
    drect(x,y+h-1,x+w-1,y+h-1,c);
    drect(x,y,x,y+h-1,c);
    drect(x+w-1,y,x+w-1,y+h-1,c);
}

/* ── Board squares ─────────────────────────────────────────────────────── */
static void draw_squares(Move last){
    for(int r=0;r<8;r++) for(int c=0;c<8;c++){
        int x=BX+c*CS, y=BY+r*CS;
        int lm=(last.fr==r&&last.fc==c)||(last.tr==r&&last.tc==c);
        int col;
        if(lm)              col=C_LASTMOVE;
        else if((r+c)%2==0) col=C_LIGHT_SQ;
        else                col=C_DARK_SQ;
        fill(x,y,CS,CS,col);
    }
}

/* ── Piece glyphs ──────────────────────────────────────────────────────── */
static void draw_pieces(int board[8][8], Move last){
    for(int r=0;r<8;r++) for(int c=0;c<8;c++){
        int p=board[r][c]; if(!p) continue;
        int x=BX+c*CS, y=BY+r*CS;
        int lm=(last.fr==r&&last.fc==c)||(last.tr==r&&last.tc==c);
        int sq_bg;
        if(lm)              sq_bg=C_LASTMOVE;
        else if((r+c)%2==0) sq_bg=C_LIGHT_SQ;
        else                sq_bg=C_DARK_SQ;
        int white=p>0, pt=abs(p);
        int fg=white?C_WHITE_P:C_BLACK_P;
        /* Shadow for white pieces on light squares */
        if(white&&(r+c)%2==0)
            draw_glyph(x+(CS-5)/2+1,y+(CS-7)/2+1,pt,C_OUTLINE,sq_bg);
        draw_glyph(x+(CS-5)/2,y+(CS-7)/2,pt,fg,sq_bg);
    }
}

/* ── Cursor ────────────────────────────────────────────────────────────── */
static void draw_cursor(int r,int c,int col){
    int x=BX+c*CS, y=BY+r*CS;
    draw_border(x,y,CS,CS,col);
    draw_border(x+1,y+1,CS-2,CS-2,col);
}

/* ── Move hints ────────────────────────────────────────────────────────── */
static void draw_hints(MoveList *ml, int board[8][8]){
    for(int i=0;i<ml->n;i++){
        int tr=ml->m[i].tr, tc=ml->m[i].tc;
        int x=BX+tc*CS, y=BY+tr*CS;
        if(board[tr][tc]!=EMPTY){
            draw_border(x+1,y+1,CS-2,CS-2,C_CAPTURE);
            draw_border(x+2,y+2,CS-4,CS-4,C_CAPTURE);
        } else {
            int cx=x+CS/2, cy=y+CS/2;
            fill(cx-2,cy-2,5,5,C_HINT);
        }
    }
}

/* ── Check highlight ───────────────────────────────────────────────────── */
static void draw_check(const Position *pos, int white){
    if(!in_check(pos,white)) return;
    int kr,kc; find_king(pos,white,&kr,&kc);
    int x=BX+kc*CS, y=BY+kr*CS;
    draw_border(x,y,CS,CS,C_CHECK);
    draw_border(x+1,y+1,CS-2,CS-2,C_CHECK);
}

/* ── Coordinates ───────────────────────────────────────────────────────── */
static void draw_coords(){
    char buf[2]={0,0};
    for(int i=0;i<8;i++){
        buf[0]='8'-i;
        dtext(BX-10,BY+i*CS+8,C_DIM,buf);
        buf[0]='a'+i;
        dtext(BX+i*CS+8,BY+8*CS+2,C_DIM,buf);
    }
}

/* ── Right panel ───────────────────────────────────────────────────────── */
static void draw_panel(int diff, int white_turn, const char *status,
                       int wtime, int btime, int move_num,
                       int w_score, int b_score, int ai_thinking){
    int px=PANEL_X, pw=SW-px;
    fill(px,0,pw,SH,C_PANEL);

    /* Title */
    dtext(px+2,2,C_TITLE,"CHESS");

    /* Difficulty tabs */
    static const char *dlbl[3]={"EZ","MD","HD"};
    static const int dcol[3]={C_EASY,C_MED,C_HARD};
    for(int i=0;i<3;i++){
        int active=(diff==i);
        int bx=px+2+i*22, by=14;
        fill(bx,by,20,11,active?dcol[i]:C_PANEL);
        draw_border(bx,by,20,11,dcol[i]);
        dtext(bx+4,by+2,active?C_BG:dcol[i],dlbl[i]);
    }
    dtext(px+2,12,C_DIM,"F1 F2 F3");

    /* Turn */
    int y=30;
    dtext(px+2,y,C_DIM,"TURN:"); y+=10;
    dtext(px+2,y,white_turn?C_WHITE_P:C_DIM,white_turn?"WHITE":"BLACK"); y+=12;

    /* Status */
    int sc=C_TEXT;
    if(status[0]=='C'&&status[1]=='h') sc=C_RED;
    else if(status[0]=='Y'&&status[1]=='o') sc=C_GREEN;
    else if(status[0]=='A'&&status[1]=='I') sc=C_GOLD;
    dtext(px+2,y,sc,status); y+=12;
    if(ai_thinking){ dtext(px+2,y,C_GREEN,"AI..."); y+=10; }

    /* Timers */
    char buf[12];
    dtext(px+2,y,C_DIM,"CLOCKS"); y+=10;
    int wc=white_turn?C_GOLD:C_TEXT, bc=!white_turn?C_GOLD:C_DIM;
    snprintf(buf,12,"W %02d:%02d",wtime/60,wtime%60);
    dtext(px+2,y,wc,buf); y+=10;
    snprintf(buf,12,"B %02d:%02d",btime/60,btime%60);
    dtext(px+2,y,bc,buf); y+=12;

    /* Move number & score */
    snprintf(buf,12,"MV:%d",move_num);
    dtext(px+2,y,C_DIM,buf); y+=10;
    snprintf(buf,12,"W+%d",w_score);
    dtext(px+2,y,C_WHITE_P,buf); y+=10;
    snprintf(buf,12,"B+%d",b_score);
    dtext(px+2,y,C_DIM,buf); y+=14;

    /* Key hints */
    static const char *hints[]={"F4 New","EXE Sel","DEL Clr","EXIT Quit"};
    for(int i=0;i<4;i++){ dtext(px+2,y,C_DIM,hints[i]); y+=10; }
}

/* ── Game-over overlay ─────────────────────────────────────────────────── */
static void draw_gameover(const char *msg, const char *sub){
    int ox=BX+16,oy=BY+72,ow=CS*8-32,oh=52;
    fill(ox-2,oy-2,ow+4,oh+4,C_GOLD);
    fill(ox,oy,ow,oh,C_BG);
    int cx=ox+ow/2;
    dtext(cx-(int)strlen(msg)*3,oy+8, C_GOLD,msg);
    dtext(cx-(int)strlen(sub)*3, oy+22,C_TEXT,sub);
    dtext(cx-15,                 oy+36,C_DIM, "F4=New game");
}

/* ═══════════════════════════════════════════════════════════════════════════
*  TIMER  (RTC-based second counter via gint rtc)
* ═══════════════════════════════════════════════════════════════════════════ */
static volatile int g_tick=0;
static int timer_id=-1;

static int tick_handler(void){
    g_tick++;
    return TIMER_CONTINUE;
}

/* ═══════════════════════════════════════════════════════════════════════════
*  MAIN
* ═══════════════════════════════════════════════════════════════════════════ */
int main(void){
    /* Start a 1-second repeating timer */
    timer_id=timer_setup(TIMER_ANY, 1000*1000, tick_handler);
    if(timer_id>=0) timer_start(timer_id);

    Position pos;
    pos_init(&pos);

    int cursor_r=6, cursor_c=4;
    int sel_r=-1, sel_c=-1;
    MoveList dests; dests.n=0;
    int diff=1;                 /* 0=easy 1=medium 2=hard  */
    int game_over=0;
    char status[24]="Your turn";
    char go_msg[24]="", go_sub[24]="";
    Move last_move; last_move.fr=last_move.fc=last_move.tr=last_move.tc=-1;
    int wtime=0, btime=0, last_tick=0;
    int w_score=0, b_score=0;
    int ai_thinking=0;
    Move ai_pending; ai_pending.fr=-1;

    for(;;){
        /* ── Clock update ─────────────────────────────────────────────── */
        int now=g_tick;
        int delta=now-last_tick; last_tick=now;
        if(!game_over && delta>0){
            if(pos.white_turn) wtime+=delta; else btime+=delta;
        }

        /* ── AI turn ──────────────────────────────────────────────────── */
        if(!game_over && !pos.white_turn && !ai_thinking){
            ai_thinking=1;
            /* redraw to show "AI..." */
            dclear(C_BG);
            draw_squares(last_move);
            draw_coords();
            draw_check(&pos,pos.white_turn);
            draw_pieces(pos.board,last_move);
            draw_panel(diff,pos.white_turn,status,wtime,btime,
                       pos.full_moves,w_score,b_score,1);
            dupdate();

            Move best; best.fr=-1;
            minimax(&pos,AI_DEPTH[diff],-100000,100000,0,&best);
            ai_thinking=0;

            if(best.fr>=0){
                int cap=apply_move(&pos,best);
                if(cap) b_score+=PIECE_VAL[cap]/100;
                last_move=best;

                MoveList ml; legal_moves_all(&pos,&ml);
                if(!ml.n){
                    game_over=1;
                    if(in_check(&pos,pos.white_turn)){
                        strcpy(go_msg,"CHECKMATE!"); strcpy(go_sub,"AI wins  F4=new");
                        strcpy(status,"You lost");
                    } else {
                        strcpy(go_msg,"STALEMATE"); strcpy(go_sub,"Draw  F4=new");
                        strcpy(status,"Stalemate");
                    }
                } else {
                    if(in_check(&pos,pos.white_turn)) strcpy(status,"Check!");
                    else strcpy(status,"Your turn");
                }
            } else {
                game_over=1;
                strcpy(go_msg,"AI RESIGNED"); strcpy(go_sub,"You win!  F4=new");
                strcpy(status,"AI resigned");
            }
        }

        /* ── Draw ─────────────────────────────────────────────────────── */
        dclear(C_BG);
        draw_squares(last_move);
        draw_coords();
        draw_check(&pos,pos.white_turn);
        if(dests.n) draw_hints(&dests,pos.board);
        if(sel_r>=0) draw_cursor(sel_r,sel_c,C_SELECTED);
        draw_cursor(cursor_r,cursor_c,C_CURSOR);
        draw_pieces(pos.board,last_move);
        draw_panel(diff,pos.white_turn,status,wtime,btime,
                   pos.full_moves,w_score,b_score,ai_thinking);
        if(game_over) draw_gameover(go_msg,go_sub);
        dupdate();

        /* ── Input (non-blocking poll) ────────────────────────────────── */
        int k=getkey_opt(GETKEY_NONE,NULL);
        if(!k) continue;   /* no key, keep looping (timer/AI updates) */

        /* EXIT */
        if(k==KEY_EXIT) break;

        /* F4 – new game */
        if(k==KEY_F4){
            pos_init(&pos);
            cursor_r=6; cursor_c=4;
            sel_r=-1; dests.n=0;
            game_over=0; ai_thinking=0;
            last_move.fr=last_move.fc=last_move.tr=last_move.tc=-1;
            wtime=0; btime=0; w_score=0; b_score=0;
            strcpy(status,"Your turn"); go_msg[0]=0; go_sub[0]=0;
            continue;
        }

        /* Difficulty (only when human's turn and not game over) */
        if(k==KEY_F1&&!game_over&&pos.white_turn){ diff=0; strcpy(status,"Easy mode"); continue; }
        if(k==KEY_F2&&!game_over&&pos.white_turn){ diff=1; strcpy(status,"Medium mode"); continue; }
        if(k==KEY_F3&&!game_over&&pos.white_turn){ diff=2; strcpy(status,"Hard mode"); continue; }

        if(game_over) continue;
        if(!pos.white_turn) continue;   /* human only plays white */

        /* DEL – deselect */
        if(k==KEY_DEL){ sel_r=-1; dests.n=0; strcpy(status,"Your turn"); continue; }

        /* Cursor movement */
        if(k==KEY_UP    && cursor_r>0){ cursor_r--; continue; }
        if(k==KEY_DOWN  && cursor_r<7){ cursor_r++; continue; }
        if(k==KEY_LEFT  && cursor_c>0){ cursor_c--; continue; }
        if(k==KEY_RIGHT && cursor_c<7){ cursor_c++; continue; }

        /* EXE */
        if(k==KEY_EXE){
            int r=cursor_r, c=cursor_c;

            if(sel_r<0){
                /* Select own piece */
                int p=pos.board[r][c];
                if(p>0){
                    legal_dests_for(&pos,r,c,&dests);
                    if(dests.n){ sel_r=r; sel_c=c; strcpy(status,"Move where?"); }
                    else strcpy(status,"No moves");
                }
            } else {
                /* Check if destination */
                int found=-1;
                for(int i=0;i<dests.n;i++)
                    if(dests.m[i].tr==r&&dests.m[i].tc==c){ found=i; break; }

                if(found>=0){
                    /* Commit move */
                    int cap=apply_move(&pos,dests.m[found]);
                    if(cap) w_score+=PIECE_VAL[cap]/100;
                    last_move=dests.m[found];
                    sel_r=-1; dests.n=0;

                    /* Check game state immediately */
                    MoveList ml; legal_moves_all(&pos,&ml);
                    if(!ml.n){
                        game_over=1;
                        if(in_check(&pos,pos.white_turn)){
                            strcpy(go_msg,"CHECKMATE!"); strcpy(go_sub,"You win!  F4=new");
                            strcpy(status,"Checkmate!");
                        } else {
                            strcpy(go_msg,"STALEMATE"); strcpy(go_sub,"Draw  F4=new");
                            strcpy(status,"Stalemate");
                        }
                    } else {
                        strcpy(status,"AI thinking...");
                    }

                } else if(pos.board[r][c]>0){
                    /* Reselect different piece */
                    legal_dests_for(&pos,r,c,&dests);
                    if(dests.n){ sel_r=r; sel_c=c; strcpy(status,"Move where?"); }
                    else { sel_r=-1; dests.n=0; strcpy(status,"No moves"); }
                } else {
                    sel_r=-1; dests.n=0; strcpy(status,"Your turn");
                }
            }
        }
    }

    if(timer_id>=0) timer_stop(timer_id);
    return 1;
}

Here is CMakeLists.txt:

cmake_minimum_required(VERSION 3.15)
project(chess)

# ── fxSDK toolchain must be active ───────────────────────────────────────────
# Run:  fxsdk build-cg
# or:   cmake -B build -DCMAKE_TOOLCHAIN_FILE=/path/to/fxSDK/toolchain.cmake
#       cmake --build build

include(GenerateG3A)   # provided by fxSDK; also handles .g4m for CG100

set(SOURCES
    src/main.c
)

# ── Add-in target ─────────────────────────────────────────────────────────────
fxconv_declare_assets(${SOURCES} WITH_BUILTIN_FONT)

add_executable(chess ${SOURCES})

target_compile_options(chess PRIVATE
    -Wall -Wextra -O2
    -ffunction-sections -fdata-sections
)

target_link_options(chess PRIVATE
    -Wl,--gc-sections
)

# Link gint (Gint runtime + CASIO OS bindings)
find_package(Gint 2.9 REQUIRED)
target_link_libraries(chess Gint::Gint)

# ── Generate the .g4m add-in file ─────────────────────────────────────────────
# Icon files: icon-cg.png must be 92×64 pixels (provided in assets/)
generate_g3a(chess OUTPUT "chess.g4m"
    NAME        "Chess AI"
    ICON        "${CMAKE_SOURCE_DIR}/assets/icon.png"
)


Fichier joint


Cakeisalie5 Hors ligne Ancien administrateur Points: 2035 Défis: 11 Message

Citer : Posté le 08/03/2026 07:05 | #


Hi, sorry Planète Casio is not an online free sweatshop for processing and fixing your ChatGPT or other AI output. If you post about your setup issues with fxSDK, we can probably help you fix it however, so you can try making your add-in yourself. Keep in mind though that calculators don't have an awful lot of memory safety like other platforms do, and a bad add-in could brick your calculator.
Lephenixnoir En ligne Administrateur Points: 25737 Défis: 174 Message

Citer : Posté le 08/03/2026 10:14 | #


There's also a bunch of mistakes in the code and some of the stuff is legendary in how incorrect it is. QVGA 384x216, sure mate. Clearly not enough gint code in the training set of it to understand the APIs properly. What a shitshow this is...
Mon graphe (27 Juin): (MQ || Rogue Life) ; serial gint ; passe gint 3 ; Azur ; ...) || (shoutbox v5 ; v5)

LienAjouter une imageAjouter une vidéoAjouter un lien vers un profilAjouter du codeCiterAjouter un spoiler(texte affichable/masquable par un clic)Ajouter une barre de progressionItaliqueGrasSoulignéAfficher du texte barréCentréJustifiéPlus petitPlus grandPlus de smileys !
Cliquez pour épingler Cliquez pour détacher Cliquez pour fermer
Alignement de l'image: Redimensionnement de l'image (en pixel):
Afficher la liste des membres
:bow: :cool: :good: :love: ^^
:omg: :fusil: :aie: :argh: :mdr:
:boulet2: :thx: :champ: :whistle: :bounce:
valider
 :)  ;)  :D  :p
 :lol:  8)  :(  :@
 0_0  :oops:  :grr:  :E
 :O  :sry:  :mmm:  :waza:
 :'(  :here:  ^^  >:)

Σ π θ ± α β γ δ Δ σ λ
captcha
Rafraîchissez la page si vous souhaitez obtenir un nouveau CAPTCHA.

Planète Casio v4.3 © créé par Neuronix et Muelsaco 2004 - 2026 | Il y a 87 connectés | Nous contacter | Qui sommes-nous ? | Licences et remerciements

Planète Casio est un site communautaire non affilié à Casio. Toute reproduction de Planète Casio, même partielle, est interdite.
Les programmes et autres publications présentes sur Planète Casio restent la propriété de leurs auteurs et peuvent être soumis à des licences ou copyrights.
CASIO est une marque déposée par CASIO Computer Co., Ltd