#include #include #include #include #include #include #include "gfx.h" #include "main.h" #include "gui.h" int loop; float sum; butt butts; tbuff texts; std::string output; //0 is nothing, 1 is hit, 2 is miss //orientation //0 : > //1 : /\ //2 : < // 3 : V //mask 11000000 //which ship mask : 00000111 //hit or miss 00010000 // whether it is anchor 00100000 char pfield [10][10]; char ofield [10][10]; //game state checking int ship; // ship currently placed, int dir; int game = 0;// determines whether it is the game or not; //boat placing time : 0 //player finsihed placing but computer not placed : 2 //game 1: //player won :-1 //opponent won : -2 bool turn;// which player's turn //texture pointers SDL_Texture * hittp; SDL_Texture * misstp; SDL_Texture * shiptp; SDL_Color red; SDL_Color white; int aihits = 0; int main (int argc, char * argv[]) { //inits program initgfx(600,800, "SDL battleship"); //main loop, this is defined in main.h and global loop = 1; hittp = loadtexture("img/hit.bmp"); misstp = loadtexture("img/miss.bmp"); shiptp = loadtexture("img/ship.bmp"); //white color preset white.r = 255; white.g = 255; white.b = 255; white.a = 255; //red color preset red.r = 255; red.g = 0; red.b = 0; red.a = 255; //adds the gui elements int si = 0; int sj = 0; srandom(time(NULL)); while (si < 10) { sj = 0; while (sj < 10) { // the fields occupy the left 400px, so 40 per thing, 30 buttons butts.add(10 + 30 * si,10 + 30 * sj,20,20, "[]"); pfield[si][sj] = 0; ofield[si][sj] = 0; sj++; } si++; } si = 0; sj = 0; while (si < 10) { sj = 0; while (sj < 10) { // the fields occupy the left 400px, so 40 per thing, 30 buttons butts.add(10 + 30 * si,500 + 30 * sj,20,20, "[]"); sj++; } si++; } butts.add(580,0,20,20, "x"); butts.add(310,700,90,40, "rotate:L"); butts.add(500,700,90,40, "rotate:R"); butts.add(400,500,110,20, "bts:4"); butts.add(400,540,80,20, "sub:3"); butts.add(400,580,80,20, "des:3"); butts.add(400,620,50,20, "pat:2"); butts.add(400,660,140,20, "car:5"); butts.add(560,30,100,20,"save"); // 208 //loads the game; if (argc >= 2) { int rlx = 0; int rly = 0; while (rlx < 10) { rly = 0; while (rly < 10) { ofield[rlx][rly] = (readfile(((std::string)argv[1] + (std::string)"o").c_str()).c_str())[rly + 10 * rlx]; pfield[rlx][rly] = (readfile(((std::string)argv[1] + (std::string)"p").c_str()).c_str())[rly + 10 * rlx]; rly++; } rlx++; } } while(loop) { //polls events, which are in a buffer //returns 1 if there is event in buffer //returns 0 if buffer is empty SDL_Event event; while (SDL_PollEvent(&event)) { switch (event.type) { //loop is a global defined in main.h case SDL_QUIT: //printf("loop = 0;\n"); loop = 0; break; //adds to the text input manager case SDL_TEXTINPUT: //if the input buffer was empty before, //make it the text, which is char[] which //is *char texts.charin( event.text.text); //printf("text input event\n"); break; //this only applies if you're typing in chinese case SDL_TEXTEDITING: //printf("text editing event\n"); break; //for when the moose moves case SDL_MOUSEMOTION: butts.hover(event.motion.x, event.motion.y); texts.hover(event.motion.x, event.motion.y); break; //left click only, double clicks cancer out so only odd case SDL_MOUSEBUTTONDOWN: if(( event.button.button == SDL_BUTTON_LEFT) && ((event.button.clicks % 2) != 0)) { if (butts.press(event.button.x, event.button.y) != -1) { } else { ship = 0; int i = 1; while (i <= 5) { butts.unpress(i + 200 + 3 + -1); i++; } } texts.press(event.button.x, event.button.y); } break; } } cleargfx(); //draws all buttons butts.drawbutt(); //draws text buffer texts.drawtbuff(); checkfieldbutts(true); // this draws hover shadow checkfieldbutts(false); checkships(true); // this draws ship lost xs checkships(false); checkshipbutts(); // this draws nothing AI(); if (butts.state(200) & TOGGLE) { loop = false; } if (butts.state(208) & TOGGLE) { butts.unpress(208); writefile("savep",pfield); writefile("saveo",ofield); } checkrotbutts(); drawfield(true); // this draws ships and pegs drawfield(false); //updates frame //since only error is an exception //all the work is done here drawrect(400,10,110,20, 120,120,120,255); drawtext(400,10,"bts:4",white); drawrect(400,50,80,20, 120,120,120,255); drawtext(400,50,"sub:3",white); drawrect(400,90,80,20, 120,120,120,255); drawtext(400,90,"des:3",white); drawrect(400,130,50,20, 120,120,120,255); drawtext(400,130,"pat:2",white); drawrect(400,170,140,20, 120,120,120,255); drawtext(400,170,"car:5",white); drawtext(200,375,"/---=[OPPONENT]=---\\",red); drawtext(200,405,"\\---=[ PLAYER ]=---/",red); if ((game == 0) || (game == 2)) { drawtext(200,391,"<--------VS-------->",red); } if (game == 1) { if (turn) { drawtext(200,391,"<---PLAYER TURN---->",red); } else { drawtext(200,391,"<-----AI TURN------>",red); } } if (game == -1) { drawtext(200,391,"<----PLAYER WON---->",red); } if (game == -2) { drawtext(200,391,"<---PLAYER LOST---->",red); } //drawgrid(0,0,1,1,true,hittp); //drawgrid(4,5,1,3,true,shiptp); //drawgrid(0,5,1,1,false,misstp); updategfx(); } SDL_DestroyTexture(hittp); SDL_DestroyTexture(misstp); SDL_DestroyTexture(shiptp); quitgfx(); return 0; } int getlen(int ship) { switch(ship) { default: return 0; break; case 1: return 4; break; case 2: return 3; break; case 3: return 3; break; case 4: return 2; break; case 5: return 5; break; } } void checkshipbutts () { int i = 1; int offset = -1 + 200 + 3; while (i <= 5) { if (butts.state(offset + i) & TOGGLE) { butts.unpress(offset + i); eraseship(i); ship = i; } i++; } } void drawgrid(int x, int y,int w,int h, bool player, SDL_Texture * t) { if (player) { x = x * 30 + 10; y = y * 30 + 500; } else { x = x * 30 + 10; y = y * 30 + 10; } w = w * 20 + (w- 1) * 10; h = h * 20 + (h- 1) * 10; drawimg(x, y, w, h, t); } // no sanity checking here. void drawfield(bool player) { int i = 0; int j = 0; if (player) { i = 0 ; j = 0; while (i < 10) { j = 0; while ( j < 10) { char peg; peg = pfield[i][j]; if ((peg & 0b00100000) != 0) { drawship (i,j, peg); } j++; } i++; } } i = 0; j = 0; if (player) { aihits = 0; } while (i < 10) { j = 0; while ( j < 10) { char peg; if (player) { peg = pfield[i][j]; } else { peg = ofield[i][j]; } if (peg & 0b00010000) { if ((peg & 0b0000111 )!= 0) { drawgrid(i, j, 1, 1,player, hittp); if (player) { aihits++; } //printf("AIHIT%d\n",aihits); } else { drawgrid(i, j, 1, 1,player, misstp); } } j++; } i++; } } void checkfieldbutts(bool player) { int i = 0; int j = 0; while (i < 10) { j = 0; while (j < 10) { if (player ) { if (game == 1) { } else if (game == 0) { if (ship != 0) { if (butts.state(i * 10 + j + 100) & TOGGLE) { placeship(i,j,ship,dir,true); ship = 0; } if (butts.state(100 + i * 10 + j) & HOVER) { switch(dir) { case 0: drawgrid(i,j,getlen(ship),1,true,shiptp); break; case 1: drawgrid(i,j - getlen(ship) + 1,1,getlen(ship),true,shiptp); break; case 2: drawgrid(i - getlen(ship) + 1,j,getlen(ship),1,true,shiptp); break; case 3: drawgrid(i,j,1,getlen(ship),true,shiptp); break; } } } } butts.unpress(100 + i* 10 + j); } else { if(game == 1) { if(turn) { if (butts.state(i * 10 + j) & TOGGLE) { if (( ofield[i][j] & 0b00010000) == 0) { turn = !turn; ofield[i][j] = ofield[i][j] | 0b00010000; } } } } else { } butts.unpress(i * 10 + j); } j++; } i++; } } void checkrotbutts() { if (butts.state(201) & TOGGLE) { butts.unpress(201); dir++; dir = dir % 4; } if (butts.state(202) & TOGGLE) { butts.unpress(202); dir--; dir = (4 + dir) % 4; } } void drawship (int x,int y, char data) { char rdir = ((data & 0b11000000) >> 6); char rship = data & 0b0000111; switch(rdir) { case 0: drawgrid(x,y,getlen(rship),1,true,shiptp); break; case 1: drawgrid(x,y - getlen(rship) + 1,1,getlen(rship),true,shiptp); break; case 2: drawgrid(x - getlen(rship) + 1,y,getlen(rship),1,true,shiptp); break; case 3: drawgrid(x,y,1,getlen(rship),true,shiptp); break; } } void eraseship(int rship) { int i = 0; int j = 0; while (i < 10) { j = 0; while (j < 10) { if ((pfield[i][j] & 0b00000111) == rship ) { pfield[i][j] = 0; } j++; } i++; } } void checkships (bool player) { int ships [5]; int ri = 0; while (ri < 5) { ships[ri] = -1; ri++; } int si = 0; int ji = 0; while (si < 10) { ji = 0; while (ji < 10) { char peg; if (player) { peg = pfield[si][ji]; } else { peg = ofield[si][ji]; } if (peg & 0b00100000) { //ships[((int)(peg & 0b00000111)) - 1] = 0; if (ships[(peg & 0b00000111) - 1] == -1) { ships[(peg & 0b00000111) - 1] = 0; } } if ((peg & 0b00000111) && (peg & 0b00010000)) { if (ships[(peg & 0b00000111) - 1] == -1) { ships[(peg & 0b00000111) - 1] = 1; } else { ships[(peg & 0b00000111) - 1]++; } } ji++; } si++; } bool allplaced = true; ri = 0; while (ri < 5) { if (ships[ri] == -1 ) { allplaced = false; } //printf("chcking ship %d with hitnum %d\n",ri+1,ships[ri]); ri++; } if (allplaced) { if (game == 0) { if (player) { game = 2; } } bool allsunk = true; ri = 0; while (ri < 5) { if (ships[ri] == getlen(ri + 1) ) { if (!player) { //to show whether a ship is down drawtext(370,10 + 40 * ri,"X",red); } else { //your stuff drawtext(370,500 + 40 * ri,"X",red); } } else { allsunk = false; } ri++; } if (allsunk) { if(player) { game = -2; } else { game = -1; } } } //printf("game state:%d\n",game); } bool placeship(int rx, int ry, int rship,int rdir, bool player) { int len = 0; bool valid = true; while (len < getlen(rship)) { int x = rx; int y = ry; switch(rdir) { case 0: x+=len; break; case 1: y-=len; break; case 2: x-=len; break; case 3: y+=len; break; } if ((x < 0 )||(x >= 10)) { valid = false; } if ((y < 0 )||(y >= 10)) { valid = false; } if (pfield[x][y] & 0b111) { if (player) { valid = false; } } if (ofield[x][y] & 0b111) { if (!player) { valid = false; } } len++; } if (valid) { //printf("placed a ship %d\n",rship); len = 0; while (len < getlen(rship)) { int x = rx; int y = ry; switch(rdir) { case 0: x+=len; break; case 1: y-=len; break; case 2: x-=len; break; case 3: y+=len; break; } if (player) { pfield[x][y] = rship | (rdir << 6); } else { ofield[x][y] = rship | (rdir << 6); } len++; } if (player) { pfield[rx][ry] = (pfield[rx][ry] | 0b0100000); } else { ofield[rx][ry] = (ofield[rx][ry] | 0b0100000); } } //printf("VALID:%d\n",valid); return valid; } void AI() { //printf("R:%d\n",randr(0,9)); if (game == 2) { int i = 1; while (i <= 5) { bool valid = placeship(randr(0,9),randr(0,9),i,randr(0,3),false); while (!valid) { valid = placeship(randr(0,9),randr(0,9),i,randr(0,3),false); } i++; } game = 1; } if (game == 1) { if(!turn) { int score[30]; int xs[30]; int ys[30]; int tscore = -99; int tpick = -1; int i = 0; while (i < 30) { bool valid = false; while (!valid) { int tx = randr(0,9); int ty = randr(0,9); if (( pfield[tx][ty] & 0b00010000) == 0) { xs[i] = tx; ys[i] = ty; score[i] =getscore(tx,ty); if (tpick == -1) { tscore = score[i]; tpick = i; } else { if (tscore < score[i]) { tscore = score[i]; tpick = i; } } valid = true; } else { valid = false; } } i++; } pfield[xs[tpick]][ys[tpick]] = pfield[xs[tpick]][ys[tpick]] | 0b00010000; turn = !turn; } } //printf("ai:%d\n",aihits); } int getscore(int x, int y) { int score; if (x < 9) { char peg = pfield[x + 1][y + 0]; if((peg & 0b00010000) != 0) { if ((peg & 0b00000111) != 0) { score += aihits / 5 + 3; } else { score--; } } else { score += 2; } } if (y < 9) { char peg = pfield[x + 0][y + 1]; if((peg & 0b00010000) != 0) { if ((peg & 0b00000111) != 0) { score += aihits / 5 + 3; } else { score--; } } else { score += 2; } } if (x > 0) { char peg = pfield[x - 1][y + 0]; if((peg & 0b00010000) != 0) { if ((peg & 0b00000111) != 0) { score += aihits / 5 + 3; } else { score--; } } else { score += 2; } } if (y > 0) { char peg = pfield[x + 0][y - 1]; if((peg & 0b00010000) != 0) { if ((peg & 0b00000111) != 0) { score += aihits / 5 + 3; } else { score--; } } else { score += 2; } } return score; } int randr(int min, int max) { int r = (min + (random() /(( RAND_MAX - 1) / (max + 1)))); //printf("r:%d,min:%d,max:%d\n",r,min,max); return r; } std::string readfile(char const * filename) { std::ifstream filebuffer; std::string line; std::string rstr; rstr = ""; char c; filebuffer.open(filename); if (!filebuffer.is_open()) { printf("error reading file"); } while (filebuffer.get(c)) { rstr = rstr + c; } filebuffer.close(); return rstr; } void writefile(char const * filename, char data[10][10]) { std::ofstream filebuffer; filebuffer.open(filename); if (!filebuffer.is_open()) { printf("error reading file"); } int r = 0; while (r < 10) { filebuffer.write(data[r],10); r++; } filebuffer.close(); }