&unotifies)
{
string error;
setactivity();
VARVAL notify_var;
notify_var.var = VAR_NOTIFY;
if (ctx.maywrite){
if (player1.name.size() == 0){
player1.name = ctx.username;
js_find_set(notify_var.val,"player0","innerHTML",ctx.username);
}else if (player2.name.size() == 0){
player2.name = ctx.username;
js_find_set(notify_var.val,"player1","innerHTML",ctx.username);
}
}
bool reverse = sessions[ctx.session];
if (strcmp(var,"print")==0){
string lines;
if (strcmp(val,"console")==0){
//static const char *white = "\033[01;37m";
//static const char *green = "\033[01;32m";
//static const char *blue = "\033[01;34m";
//static const char *red = "\033[01;31m";
static const char *bgblue = "\033[01;44m";
static const char *bggreen = "\033[01;42m";
static const char *bgred = "\033[01;41m";
static const char *bgblack = "\033[01;40m";
static const char *normal = "\033[00m";
static const char *tbcolor[]={bgblack,bgblue};
unsigned nol = 0;
for (auto &g:grid){
static const char *tbl[]={
"%s %s %s ",
"%s %s %s ",
"%s %s %s ",
"%s %s %s ",
"%s %s %s ",
//"%s ",
};
for (unsigned i=0; i<5; i++){
unsigned color = nol & 1;
if (i == 2){
lines += string_f("\t%d ",8-nol);
}else{
lines += "\t ";
}
for (auto &gg:g){
const char *bg = tbcolor[color];
color = (color+1)&1;
const char *bg1 = "";
if (gg == 0){
bg1 = bg;
}else if (gg == 1){
bg1 = bgred;
}else if (gg == 2){
bg1 = bggreen;
}
lines += string_f(tbl[i],bg,bg1,bg);
}
lines += normal;
lines += '\n';
}
nol++;
}
lines += "\t ";
for (unsigned i=0; i<8; i++) lines += string_f(" %c ",i+'A');
lines += '\n';
}else{
// tlmp_warning ("sp w=%u h=%u cw=%u ch=%u",sp.width,sp.height,sp.content_width,sp.content_height);
// The layout is a square, constrained by the width
unsigned reverse_width = sp.mobile ? 45 : 25;
unsigned reverse_margin = 25;
unsigned waiting_users_width = sp.mobile ? 62 : 42;
unsigned limited_width = sp.content_width - (reverse_width+reverse_margin+waiting_users_width);
unsigned dim = limited_width < sp.content_height ? limited_width : sp.content_height;
unsigned width = dim - dim % nbcol;
unsigned w8 = width/(nbcol);
unsigned h8 = w8;
unsigned grid_width = w8*nbcol;
unsigned grid_height = w8*nbcol;
lines += "\n";
lines += "\n";
lines += string_f("\n",val);
lines += string_f("
\n",reverse_margin);
lines += string_f("
\n",reverse_width,grid_height,reverse_width,grid_height);
lines += string_f(" \n"
,reverse_width,grid_height);
{
// Draw a vertical arrow
unsigned h1 = reverse_width/2;
unsigned v1 = grid_height/4;
unsigned vlen = grid_height/2;
lines += string_f(" \n"
,h1,v1,vlen);
lines += string_f(" \n"
,h1-5,v1+5,h1,v1,h1+5,v1+5);
lines += string_f(" \n"
,h1-5,v1+vlen-5,h1,v1+vlen,h1+5,v1+vlen-5);
}
lines += " \n";
lines += "
\n";
lines += "
\n";
lines += string_f("
\n"
,gameid.c_str(),grid_width,grid_height,grid_width,grid_height);
unsigned w8_2 = w8/2;
unsigned h8_2 = h8/2;
unsigned circle_radius = h8_2 - h8/10;
for (unsigned vline=0; vline \n"
,w8*col,h8*vline,w8,h8,w8);
}
unsigned cell = grid[line][col];
const char *fill_color = "none";
const char *stroke_color = "none";
const char *select_color = "none";
const char *king_color = "none";
if (is_any_of(cell,PLAYER1,PLAYER2,PLAYER1_KING,PLAYER2_KING)){
if (is_any_of(cell,PLAYER1,PLAYER1_KING)){
fill_color = "black";
if (cell == PLAYER1_KING) king_color = "gold";
}else{
fill_color = "red";
if (cell == PLAYER2_KING) king_color = "gold";
}
stroke_color = "black";
if (player1.col == col && player1.line == line){
select_color = "blue";
}else if (player2.col == col && player2.line == line){
select_color = "blue";
}
}
lines += string_f(" \n"
,line,col,w8_col+w8_2,h8_line+h8_2,circle_radius,stroke_color,fill_color);
lines += string_f(" \n"
,line,col,w8_col+w8_2,h8_line+h8_2,circle_radius-2,king_color,king_color);
lines += string_f(" \n"
,line,col,w8_col+w8_2,h8_line+h8_2,circle_radius-8,fill_color,fill_color);
lines += string_f(" \n"
,line,col,w8_col+w8_2,h8_line+h8_2,circle_radius-18,select_color,select_color);
}
}
lines += string_f(" \n"
,1,1,grid_width-1,grid_height-1,1);
for (unsigned vline=0; vline \n",linecolor
,0,h8*vline,grid_width);
for (unsigned col=0; col \n",linecolor
,w8*col,0,grid_height);
}
}
lines += " \n";
lines += "
\n";
draw_waiting_users(lines,waiting_users_width,grid_height,"flex:0 0 auto;");
lines += "
\n";
lines += "\n";
}
VARVAL v;
v.var = VAR_CONTENT;
v.val = lines;
res.push_back(v);
}else if (strcmp(var,"reverse")==0){
sessions[ctx.session] = !reverse;
documentd_forcerefresh(res);
}else if (strcmp(var,REQ_CHAT)==0){
appendchat(val,notify_var.val,res,ctx);
}else if (ctx.maywrite){
if (strcmp(var,"place")==0){
unsigned lo,co,button;
if (splitline(val,',',limits(lo,0u,nbcol-1),limits(co,0u,nbcol-1),enums(button,{1u,2u}))){
if (reverse) lo = nbcol -1 - lo;
CHECKER_PLAYER *player = &player2;
unsigned cell_val = PLAYER2;
unsigned cell_val_king = PLAYER2_KING;
unsigned other_player = PLAYER1;
unsigned other_player_king = PLAYER1_KING;
unsigned king_line = 0; // Line to reach to turn a coin into a king
int vmove = -1;
if (player1_playing){
player = &player1;
cell_val = PLAYER1;
cell_val_king = PLAYER1_KING;
other_player = PLAYER2;
other_player_king = PLAYER2_KING;
king_line = nbcol-1;
vmove = 1;
}
if (player->has_selected()){
if (player->line == lo && player->col == co){
// The player is unselecting the cell
if (player->onemove){
player1_playing = !player1_playing;
js_find_set(notify_var.val,"player0","style.backgroundColor",player1_playing ? "lightblue" : "white");
js_find_set(notify_var.val,"player1","style.backgroundColor",!player1_playing ? "lightblue" : "white");
}
string id = string_f("cs%u,%u",lo,co);
js_find_loop_set (notify_var.val,"grid","circle",id,"style.fill","none","style.stroke","none");
player->reset();
}else{
int left_col = player->col - 1;
int right_col = player->col + 1;
int next_line = player->line + vmove;
int left_col2 = player->col - 2;
int right_col2 = player->col + 2;
int next_line2 = player->line + vmove + vmove;
// for king moves
int prev_line = player->line - vmove;
int prev_line2 = prev_line - vmove;
unsigned char &cell = grid[lo][co];
unsigned char sel_cell = grid[player->line][player->col];
bool move_ok = false;
bool keep_playing = false;
// tlmp_warning ("sel_cell=%u cell=%u lo=%u co=%u prev_line=%u",sel_cell,cell,lo,co,prev_line);
if (cell != 0){
if (cell == WHITE){
error = MSG_U(E_CANTGOTHERE,"You are not allowed to move to white cell");
}else if (is_any_of(cell,cell_val,cell_val_king)){
error = MSG_U(E_NOJUMPONYOU,"You can't stack coins");
}else{
error = MSG_U(E_NOJUMPONOTHER,"You can't jump on the other player coin");
}
}else if (!player->onemove && (int)lo == next_line && is_any_of((int)co,left_col,right_col)){
// Move the an available next cell
move_ok = true;
}else if (!player->onemove && is_any_of(sel_cell,PLAYER1_KING,PLAYER2_KING)
&& (int)lo == prev_line && is_any_of((int)co,left_col,right_col)){
// Move the an available next cell
move_ok = true;
}else if ((int)lo == next_line2 || ((int)lo == prev_line2 && is_any_of(sel_cell,PLAYER1_KING,PLAYER2_KING))){
// Move over a player coin
int inter_line = (int)lo==next_line2 ? next_line : prev_line;
unsigned erase_col = 0;
if ((int)co == left_col2 && is_any_of(grid[inter_line][left_col],other_player,other_player_king)){
move_ok = true;
grid[inter_line][left_col] = NOTUSED;
erase_col = left_col;
}else if ((int)co == right_col2 && is_any_of(grid[inter_line][right_col],other_player,other_player_king)){
move_ok = true;
grid[inter_line][right_col] = NOTUSED;
erase_col = right_col;
}
if (move_ok){ // && (sp.mobile || button == 2)){
// Ok, we jumped over a coin, it has to be erased
for (auto c:{"c","ck","cc","cs"}){
string id = string_f("%s%u,%u",c,inter_line,erase_col);
js_find_loop_set (notify_var.val,"grid","circle",id,"style.fill","none","style.stroke","none");
}
keep_playing = true;
}
}
if (move_ok){
// Erase last selected position
for (auto c:{"c","ck","cc","cs"}){
string id = string_f("%s%u,%u",c,player->line,player->col);
js_find_loop_set (notify_var.val,"grid","circle",id,"style.fill","none","style.stroke","none");
}
// Draw the new position
const char *kcolor = is_any_of(sel_cell,PLAYER1_KING,PLAYER2_KING) ? "gold" : "none";
const char *color = player1_playing ? "black" : "red";
string id = string_f("c%u,%u",lo,co);
js_find_loop_set (notify_var.val,"grid","circle",id,"style.fill",color,"style.stroke","black");
id = string_f("ck%u,%u",lo,co);
js_find_loop_set (notify_var.val,"grid","circle",id,"style.fill",kcolor,"style.stroke",kcolor);
id = string_f("cc%u,%u",lo,co);
js_find_loop_set (notify_var.val,"grid","circle",id,"style.fill",color,"style.stroke",color);
grid[player->line][player->col] = NOTUSED;
cell = sel_cell;
if (lo == king_line){
if (cell == PLAYER1){
cell = PLAYER1_KING;
}else if (cell == PLAYER2){
cell = PLAYER2_KING;
}
string id = string_f("ck%u,%u",lo,co);
js_find_loop_set (notify_var.val,"grid","circle",id,"style.fill","gold","style.stroke","gold");
}
setmodified (ctx.username);
documentd_setchanges(res);
if (keep_playing){
player->line = lo;
player->col = co;
player->onemove = true;
id = string_f("cs%u,%u",lo,co);
const char *color = player1_playing ? "blue" : "blue";
js_find_loop_set (notify_var.val,"grid","circle",id,"style.fill",color,"style.stroke",color);
}else{
player->reset();
player1_playing = !player1_playing;
js_find_set(notify_var.val,"player0","style.backgroundColor",player1_playing ? "lightblue" : "white");
js_find_set(notify_var.val,"player1","style.backgroundColor",!player1_playing ? "lightblue" : "white");
}
}else if (error.size() == 0){
error = MSG_U(E_IVLDMOVE,"Invalid move");
}
}
}else if (is_any_of(grid[lo][co],cell_val,cell_val_king)){
// The player is about to move that piece
player->col = co;
player->line = lo;
const char *color = player1_playing ? "blue" : "blue";
string id = string_f("cs%u,%u",lo,co);
js_find_loop_set (notify_var.val,"grid","circle",id,"style.fill",color,"style.stroke",color);
}else{
documentd_error (res,"Can't select this cell");
}
}else{
tlmp_error ("checkers, invalid place command: %s",val);
}
}else if (strcmp(var,"newgame")==0){
int uval = atoi(val);
if (is_any_of(uval,0,1)){
nbcol = uval == 0 ? 8 : 10;
resetgame();
js_find_loop_start (notify_var.val,"grid","circle");
unsigned item = 0;
for (unsigned i=0; iname = ctx.username;
js_find_set(notify_var.val,"player0","innerHTML",player1.name.c_str());
js_find_set(notify_var.val,"player1","innerHTML",player2.name.c_str());
}
}else{
error = MSG_R(E_READONLY);
}
if (notify_var.val.size() > 0) res.emplace_back(notify_var);
if (error.size() > 0){
update_msg(false,error,"red",res);
}else{
update_msg(false," ","white",res);
}
}