/* This file is part of Bolixo. Bolixo is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Bolixo is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Bolixo. If not, see . */ #include #include #include #include #include #include "bolixo.h" #include "proto/bod_client.protodef" #include "documentd.h" #include "bolixo.m" using namespace std; #include "proto/documentd_tictacto.protoh" #include "proto/documentd_tictacto.protoch" class TICTACTO: public GAME{ bool x_is_player; unsigned char grid[3][3]; void update_msg (bool to_all, PARAM_STRING msg, const char *color, std::vector &res); public: void save(DOC_WRITER &w, bool); void load(DOC_READER &r, std::string &msg); void resetgame(); TICTACTO(); const char *getclass() const; void testwin(std::vector &res); void draw_x(unsigned cellx, unsigned celly, std::string &lines, unsigned x, unsigned y, unsigned len, bool visible); void draw_o(unsigned cellx, unsigned celly, std::string &lines, unsigned x, unsigned y, unsigned len, bool visible); void exec (const char *var, const char *val, const DOC_CONTEXT &ctx, const DOC_UI_SPECS_receive &sp, std::vector &res, std::vector &unotifies); }; GAME_P make_TICTACTO() { return make_shared(); } void TICTACTO::save(DOC_WRITER &w, bool) { documentd_tictacto_header(&w,revision); documentd_tictacto_player(&w,x_is_player); unsigned row=0; for (auto &g:grid){ documentd_tictacto_row(&w,row,g[0],g[1],g[2]); row++; } } void TICTACTO::load(DOC_READER &r, string &msg) { glocal x_is_player; glocal grid; glocal revision; glocal msg; (&r); glocal.revision = revision; glocal.x_is_player = x_is_player; if (rownum > 3){ glocal.msg = string_f("Invalid row number for tictacto file: %u",rownum); }else{ glocal.grid[rownum][0] = c1; glocal.grid[rownum][1] = c2; glocal.grid[rownum][2] = c3; } glocal.msg = "Invalid format for tictacto file"; } void TICTACTO::resetgame() { x_is_player = true; memset (grid,0,sizeof(grid)); } TICTACTO::TICTACTO() { resetgame(); } const char *TICTACTO::getclass() const { return "TICT"; } void TICTACTO::testwin(vector &res) { bool won = false; for (auto g:grid){ unsigned char v = g[0]; if (v != 0){ bool found = true; for (unsigned j=1; j<3; j++){ if (v != g[j]){ found = false; break; } } if (found){ won = true; break; } } } if (!won){ for (unsigned i=0; i<3; i++){ unsigned char v = grid[0][i]; if (v != 0){ bool found = true; for (unsigned j=1; j<3; j++){ if (v != grid[j][i]){ found = false; break; } } if (found){ won = true; break; } } } if (!won){ if (grid[0][0] != 0 && grid[0][0] == grid[1][1] && grid[0][0] == grid[2][2]){ won = true; }else if (grid[0][2] != 0 && grid[0][2] == grid[1][1] && grid[0][2] == grid[2][0]){ won = true; } } } if (won){ update_msg (true,MSG_U(I_WON,"Congratulation! You just won"),"blue",res); } } void TICTACTO::draw_x(unsigned cellx, unsigned celly, string &lines, unsigned x, unsigned y, unsigned len, bool visible) { const char *color = visible ? "black" : "none"; const unsigned off = len/4; x += off; y += off; len -= off*2; lines += string_f("\n" ,cellx,celly,visible ? "black" : "none",color,x,y,x+len,y+len); lines += string_f("\n" ,cellx,celly,color,color,x,y+len,x+len,y); } void TICTACTO::draw_o(unsigned cellx, unsigned celly, string &lines, unsigned x, unsigned y, unsigned len, bool visible) { const char *color = visible ? "black" : "none"; const unsigned off = len/4; x += off; y += off; len -= off*2; lines += string_f("\n" ,cellx,celly,color,x+len/2,y+len/2,len/2); } void TICTACTO::update_msg( bool to_all, // The message will be shown to all player or not PARAM_STRING msg, const char *color, vector &res) { VARVAL mvar; mvar.var = to_all ? VAR_NOTIFY : VAR_SCRIPT; js_find_set (mvar.val,"msg","style.color",color,"innerHTML",documentd_escape(msg).c_str()); res.emplace_back(mvar); } void TICTACTO::exec ( const char *var, const char *val, const DOC_CONTEXT &ctx, const DOC_UI_SPECS_receive &sp, vector &res, vector &unotifies) { string error; VARVAL notify_var; notify_var.var = VAR_NOTIFY; setactivity(); if (strcmp(var,"print")==0){ string lines; unsigned dim = sp.width < sp.height ? sp.width : sp.height; unsigned width = dim - dim % 4; //unsigned height = win_height - win_height % 3; unsigned w3 = width/4; unsigned h3 = w3; unsigned grid_width = w3*3; unsigned grid_height = grid_width; lines += "\n"; lines += string_f("
\n"); documentd_button_start(lines,gameid); documentd_button_label(lines,MSG_R(I_NEWGAME)); documentd_button (lines,0,MSG_U(I_RESTART,"Restart"),false); documentd_button_end(lines); lines += "
\n"; lines += string_f("
\n",val); lines += string_f("\n",gameid.c_str()); draw_x (0,0,lines,0,0,50,true); draw_o (0,0,lines,0,100,50,true); lines += string_f("\n" ,x_is_player ? "black" : "none",0); lines += string_f("\n" ,!x_is_player ? "black" : "none",100); lines += "\n"; lines += "   "; lines += string_f("\n" ,gameid.c_str(),grid_width,grid_height,grid_width,grid_height); // Draw the board for (unsigned i=1; i<3; i++){ lines += string_f("\n" ,i*w3,i*w3,grid_height); lines += string_f("\n" ,i*h3,grid_width,i*h3); } // Draw the content for (unsigned x=0; x<3; x++){ for (unsigned y=0; y<3; y++){ unsigned val = grid[x][y]; draw_x (x,y,lines,x*h3,y*h3,h3,val==1); draw_o (x,y,lines,x*h3,y*h3,h3,val==2); } } lines += "\n"; lines += "
\n"; lines += "
\n"; lines += string_f("
XXXXXXXX
\n",gameid.c_str()); lines += "
\n"; VARVAL v; v.var = VAR_CONTENT; v.val = lines; res.push_back(v); }else if (ctx.maywrite){ if (strcmp(var,"place")==0){ bool ok = false; unsigned x=atoi(val); const char *pt = str_skipdig(val); const char *msg = "Invalid syntax"; if (*pt == ','){ pt++; unsigned y=atoi(pt); pt = str_skipdig(pt); if (*pt == '\0'){ msg = "Invalid values"; if (x < 3 && y < 3){ unsigned char &g = grid[y][x]; if (g == 0){ g = x_is_player ? 1 : 2; js_find_loop_start_class(notify_var.val,"gamegrid","x_o"); notify_var.val += "\t\tfor (var i=0; i 0) res.emplace_back(notify_var); if (error.size() > 0){ update_msg(false,error,"red",res); }else{ update_msg(false,"","white",res); } }