#include #include #include #include #include #include #include "igo.h" enum { DGobrown=0xEE9E00FF, DSTbord=0x303030FF, Cmdmaxsz=128, ↑=61454, ↓=128, DELETEKEY=113, Stonesz=3, //divider of Δ Thickln=25, //divider of Δ Pointsz=5, //divider of Δ Countsz=5, //divider of Δ Szmin=150, Szmax=1500 }; static int Δx, Δy; static int bpoints, wpoints, clk; static Point pdr, pul; static int visible; Keyboardctl *keyboardctl; Mousectl *mousectl; static int Δx, Δy; static Point pul,fontcorn; static int bdead,wdead,clk; static Image *pixbg,*pixfg,*pixko,*pixwht,*pixst, *pixyell, *pixbl; static int drawstone(Point pos,char type); static void drawgoban(void) { int i,j; Point pos; for (i=0; idefaultfont; runesprint(r, "b: %d w: %d time: %d",bdead, wdead,time); fontcorn=runestring(screen, pul, pixfg, ZP, defont,r); } static void redraw(void) { int i; Point pur, pdl, pdr, st,end; //up down left right (pul is global) /* points on the corners of the goban*/ pul=Pt(screen->r.min.x,screen->r.min.y); pdr=Pt(screen->r.max.x,screen->r.max.y); pur.y=pul.y; pur.x=pdr.x; pdl.x=pul.x; pdl.y=pdr.y; Δx=abs(pur.x-pul.x)/(Bansz+1); Δy=abs(pdl.y-pul.y)/(Bansz+1); draw(screen, screen->r, pixbg, nil, ZP); for (i=1; i Bansz) pos.x=-1; if(pos.y > Bansz) pos.y=-1; if(pos.x < 1) pos.x=-1; if(pos.y<1) pos.y=-1; return pos; } static void initifc(void) { bdead=0; wdead=0; clk=0; visible = 1; cleangoban(); if (initdraw(nil, nil, "goifc") < 0) exits("initdraw failed"); pixbl = allocimage(display, Rect(0,0,1,1), screen->chan, 1, DBluegreen); pixbg = allocimage(display, Rect(0,0,1,1), screen->chan, 1, DGobrown); pixfg = allocimage(display, Rect(0,0,1,1), screen->chan, 1, DBlack); pixwht = allocimage(display, Rect(0,0,1,1), screen->chan, 1, DWhite); pixst = allocimage(display, Rect(0,0,1,1), screen->chan, 1, DSTbord); pixko = allocimage(display, Rect(0,0,1,1), screen->chan, 1, DRed); pixyell = allocimage(display, Rect(0,0,1,1), screen->chan, 1, DYellow); if(!pixbg||!pixfg||!pixwht||!pixst) exits("out of image memory"); redraw(); } static int drawstone(Point pos,char type) { int xpos, ypos, radx ,rady, notup, notleft, notright, notdown, i; Point lpos, st, end; if(!visible) return 0; xpos = pos.x; ypos = pos.y; notright=!(xpos==19); notleft=!(xpos==1); notup=!(ypos==19); notdown=!(ypos==1); xpos = pul.x+xpos*Δx; ypos = pul.y+ypos*Δy; lpos = Pt(xpos, ypos); radx = Δx/Stonesz; rady = Δy/Stonesz; if(type!=Emptystone && type!='p' && type!=Lstone) drawstone(pos, Emptystone); switch(type){ case Bstone: fillellipse(screen, Pt(xpos,ypos),radx,rady, pixfg, Pt(0,0)); ellipse(screen, Pt(xpos,ypos),radx-1,rady-1,1, pixst, Pt(0,0)); break; case Wstone: fillellipse(screen, Pt(xpos,ypos),radx,rady, pixwht, Pt(0,0)); ellipse(screen, Pt(xpos,ypos),radx-1,rady-1,1, pixfg, Pt(0,0)); break; case 't': dprint("triangle..."); break; case 'p': radx = Δx/Pointsz; rady = Δy/Pointsz; fillellipse(screen, Pt(xpos,ypos), radx,rady, pixfg, Pt(0,0)); break; case Cntstone: radx = Δx/Countsz; rady = Δy/Countsz; fillellipse(screen, Pt(xpos,ypos),radx,rady, pixbl, Pt(0,0)); //drawellipse("black", nil, lpos, Pt(radx, rady)); break; case Wmarked: fillellipse(screen, Pt(xpos,ypos),radx,rady, pixwht, Pt(0,0)); ellipse(screen, Pt(xpos,ypos),radx-1,rady-1,1, pixfg, Pt(0,0)); radx = Δx/Pointsz-1; rady = Δy/Pointsz-1; fillellipse(screen, Pt(xpos,ypos),radx,rady, pixyell, Pt(0,0)); //yellow and black ellipse(screen, Pt(xpos,ypos),radx-1,rady-1,1, pixfg, Pt(0,0)); break; case Bmarked: fillellipse(screen, Pt(xpos,ypos),radx,rady, pixfg, Pt(0,0)); ellipse(screen, Pt(xpos,ypos),radx-1,rady-1,1, pixst, Pt(0,0)); radx = Δx/Pointsz-1; rady = Δy/Pointsz-1; fillellipse(screen, Pt(xpos,ypos),radx,rady, pixyell, Pt(0,0)); break; case Kou: radx = Δx/Pointsz; rady = Δy/Pointsz; fillellipse(screen, Pt(xpos,ypos),radx,rady, pixko, Pt(0,0)); break; case Lstone: radx = Δx/Countsz-1; rady = Δy/Countsz-1; fillellipse(screen, Pt(xpos,ypos),radx,rady, pixko, Pt(0,0)); break; case Emptystone: fillellipse(screen, Pt(xpos,ypos), radx,rady, pixbg, Pt(0,0)); st=Pt(xpos+notright*radx+1,ypos); end=Pt(xpos-notleft*radx-1,ypos); line(screen,st,end, Endsquare, Endsquare,1, pixfg, Pt(0,0)); st=Pt(xpos,ypos+notup*rady+1); end=Pt(xpos,ypos-notdown*rady-1); line(screen,st,end, Endsquare, Endsquare,1, pixfg, Pt(0,0)); for(i=0;i<9;i++) if(pos.x==hcap[i].x && pos.y==hcap[i].y) drawstone(pos,'p'); break; default: sysfatal("drawstone: weird stone: %d", type); break; } return 0; } void opdraw(Move *m, char) { drawstone(m->Point, goban[m->x][m->y]); } Channel *ifcchan; int waskou; void ifcthread(void *) { Move *mdead, *mv; int ndead; mdead=nil; while(mv=recvp(ifcchan)){ if(moves && visible) drawstone(lstone, goban[lstone.x][lstone.y]); if(lkou.type) waskou++; ndead=move(mv,&mdead); dprint("ndead = %d\n", ndead); if(ndead >= 0 && visible && waskou){ dprint("cleaning\n"); drawstone(lkou, Emptystone); lkou.type = '\0'; } waskou = 0; if(ndead>0){ bdead+=ndead; if(visible) drwlabel(bdead,wdead,0); } if(ndead>=0){ opdraw(mv, goban[mv->x][mv->y]); opgrp(mdead, '\0', opdraw); } if(lstone.type) drawstone(lstone, Lstone); sendp(ifcchan,mdead); mdead=nil; //flushimage(display,1); } } enum{ Noev=0, Click1, Click2, Click3, }; static int mouseevrd (Mouse *mev) { int button; button=mev->buttons; if (button==1){ return Click1; } if (button==2){ return Click2; } if (button==4){ return Click3; } return 0; } enum { Akeyboard, Areshape, Amouse, NALT }; void opsend(Move *m, char) { Move *mdead; if(!m){ dprint("nil\n"); return; } m->next = nil; sendp(ifcchan,m); mdead=recvp(ifcchan); freegrp(mdead); } void inthread(void *) { int desvx,desvy, pressed, nw, nb, ndead; Point pos; static Alt alts[NALT+1]; Rune r; Mouse m; Move *mv, *mdead; threadsetname("inthread"); initifc(); alts[Akeyboard].c = keyboardctl->c; alts[Akeyboard].v = &r; alts[Akeyboard].op = CHANRCV; alts[Areshape].c = mousectl->resizec; alts[Areshape].v = nil; alts[Areshape].op = CHANRCV; alts[Amouse].c = mousectl->c; alts[Amouse].v = &m; alts[Amouse].op = CHANRCV; alts[NALT].op = CHANEND; while(1){ visible = 1; switch(alt(alts)) { case Akeyboard: if(r==DELETEKEY) threadexitsall(nil); else if(r=='q') threadexitsall(nil); else if(r=='c'){ trycount(&nw, &nb); bdead += nb; wdead += nw; drwlabel(bdead,wdead,clk); drawgoban(); flushimage(display,1); } else if(r=='u' && moves){ visible = 0; mv = moves; mv = freelast(mv); moves = nil; bdead = 0; wdead = 0; cleangoban(); if(mv) opgrp(mv, '\0', opsend); visible = 1; drwlabel(bdead,wdead,clk); drawgoban(); flushimage(display,1); } break; case Areshape: resized(1); break; case Amouse: //coordinates are global, relativice them desvx=(m.xy.x)-screen->r.min.x; desvy=(m.xy.y)-screen->r.min.y; pos=calcmove(Pt(desvx,desvy)); pressed=mouseevrd(&m); if(pressed && isvalidpos(pos)){ mv=getmove(pos); if(pressed==Click1){ mv->type='W'; sendp(ifcchan,mv); mdead=recvp(ifcchan); } else if(pressed==Click2){ mv->type='B'; sendp(ifcchan,mv); mdead=recvp(ifcchan); } else if(pressed==Click3){ if(strchr(emptytype, mv->type)!=nil) break; ndead = markdead(mv, &mdead); if(mdead->type=='B') wdead+=ndead; else if(mdead->type=='W') bdead+=ndead; drwlabel(bdead,wdead,clk); drawgoban(); } else break; flushimage(display,1); opgrp(mdead,0,opprint); freegrp(mdead); freegrp(mv); } break; } } }