ref: 04c90470556a5d3a66fb592ff7b6fee1228be95e
parent: 8285721acfc247d57e0831503543dd29290ac4c5
author: rodri <rgl@antares-labs.eu>
date: Mon Aug 14 22:41:43 EDT 2023
added ship drawing and placement procedures.
--- a/bts.c
+++ b/bts.c
@@ -19,6 +19,7 @@
Image *tiletab[NTILES];
Board alienboard;
Board localboard;
+Ship *carrier;
struct {
int state;
@@ -84,6 +85,25 @@
}
void
+drawship(Image *dst, Ship *s)
+{
+ Point2 p, sv;
+ int i;
+
+ p = s->p;
+ switch(s->orient){
+ case OH: sv = Vec2(1,0); break;
+ case OV: sv = Vec2(0,1); break;
+ default: return;
+ }
+
+ for(i = 0; i < s->ncells; i++){
+ drawtile(dst, &localboard, p, s->hit[i]? Thit: Tship);
+ p = addpt2(p, sv);
+ }
+}
+
+void
drawboard(Image *dst, Board *b)
{
int i, j;
@@ -101,6 +121,7 @@
draw(screenb, screenb->r, display->black, nil, ZP);
drawboard(screenb, &alienboard);
drawboard(screenb, &localboard);
+ drawship(screenb, carrier);
draw(screen, screen->r, screenb, nil, ZP);
@@ -191,6 +212,44 @@
}
void
+initships(void)
+{
+ Point2 sv;
+
+ carrier = emalloc(sizeof *carrier);
+ carrier->p = Pt2(2,4,1);
+ carrier->orient = OV;
+ carrier->ncells = 5;
+ carrier->hit = emalloc(carrier->ncells*sizeof(int));
+ memset(carrier->hit, 0, carrier->ncells*sizeof(int));
+ carrier->sunk = 0;
+ switch(carrier->orient){
+ case OH: sv = Vec2(1,0); break;
+ case OV: sv = Vec2(0,1); break;
+ default: sysfatal("initships: wrong ship orientation");
+ }
+ carrier->bbox = Rpt(
+ fromboard(&localboard, carrier->p),
+ fromboard(&localboard, addpt2(addpt2(carrier->p, mulpt2(sv, carrier->ncells)), Vec2(sv.y,sv.x)))
+ );
+}
+
+void
+placeship(Mousectl *mc, Ship *s)
+{
+ for(;;){
+ if(readmouse(mc) < 0)
+ break;
+ mc->xy = subpt(mc->xy, screen->r.min);
+ if(ptinrect(mc->xy, localboard.bbox) && mc->buttons == 1){
+ s->p = toboard(&localboard, mc->xy);
+ send(drawchan, nil);
+ break;
+ }
+ }
+}
+
+void
lmb(Mousectl *mc)
{
Board *b;
@@ -202,21 +261,42 @@
else if(ptinrect(mc->xy, localboard.bbox))
b = &localboard;
- if(b != nil){
- cell = toboard(b, mc->xy);
- switch(game.state){
- case Outlaying:
- settile(b, cell, Tship);
- case Playing:
- settile(b, cell, Tmiss);
- chanprint(egress, "shoot %d-%d", (int)cell.x, (int)cell.y);
- break;
- }
+ if(b == nil)
+ return;
+
+ cell = toboard(b, mc->xy);
+ switch(game.state){
+ case Outlaying:
+ settile(b, cell, Tship);
+ break;
+ case Playing:
+ settile(b, cell, Tmiss);
+ chanprint(egress, "shoot %d-%d", (int)cell.x, (int)cell.y);
+ break;
}
send(drawchan, nil);
}
void
+rmb(Mousectl *mc)
+{
+ enum {
+ PLACESHIP,
+ };
+ static char *items[] = {
+ [PLACESHIP] "place ship",
+ nil
+ };
+ static Menu menu = { .item = items };
+
+ switch(menuhit(3, mc, &menu, _screen)){
+ case PLACESHIP:
+ placeship(mc, carrier);
+ break;
+ }
+}
+
+void
mouse(Mousectl *mc)
{
mc->xy = subpt(mc->xy, screen->r.min);
@@ -226,10 +306,10 @@
lmb(mc);
break;
case 2:
- //mmb(mc);
+// mmb(mc);
break;
case 4:
- //rmb(mc);
+ rmb(mc);
break;
}
}
@@ -387,6 +467,7 @@
inittiles();
initboards();
+ initships();
game.state = Waiting0;
drawchan = chancreate(sizeof(void*), 0);
--- a/dat.h
+++ b/dat.h
@@ -5,6 +5,9 @@
Tmiss,
NTILES,
+ OH, /* horizontal */
+ OV, /* vertical */
+
Waiting0 = 0,
Outlaying,
Waiting1,
@@ -22,8 +25,8 @@
};
typedef struct Input Input;
-typedef struct Board Board;
typedef struct Ship Ship;
+typedef struct Board Board;
typedef struct Player Player;
typedef struct Playerq Playerq;
typedef struct Chanpipe Chanpipe;
@@ -34,18 +37,21 @@
Keyboardctl *kc;
};
-struct Board
+struct Ship
{
- RFrame;
- char map[17][17];
+ Point2 p; /* board cell */
Rectangle bbox;
+ int orient;
+ int ncells;
+ int *hit; /* |hit| = ncells and hit = {x: 0 ≤ x ≤ 1} */
+ int sunk;
};
-struct Ship
+struct Board
{
RFrame;
- int ncells;
- int sunk;
+ char map[17][17];
+ Rectangle bbox;
};
struct Player
@@ -52,6 +58,7 @@
{
int fd;
int sfd;
+ Channel *mc; /* for matching */
Player *o; /* opponent */
};