diff --git a/.idea/vcs.xml b/.idea/vcs.xml
index c92014d..df7a89d 100644
--- a/.idea/vcs.xml
+++ b/.idea/vcs.xml
@@ -11,10 +11,6 @@
-
-
-
-
@@ -28,6 +24,5 @@
-
\ No newline at end of file
diff --git a/data/config.json b/data/config.json
index 65edcae..600dc2f 100644
--- a/data/config.json
+++ b/data/config.json
@@ -19,7 +19,8 @@
"path": "./engine/katago",
"command": "katago",
"parameters": "gtp -model ./engine/katago/models/g170-b20c256x2-s4384473088-d968438914.bin.gz -config ./engine/katago/default_gtp.cfg",
- "enabled": 0,
+ "enabled": 1,
+ "kibitz": 1,
"messages": [
{
"regex": "^:\\s+T.*--\\s*([A-Z0-9]+)",
diff --git a/data/gui/goban.rml b/data/gui/goban.rml
index 9f879f0..bba69be 100644
--- a/data/gui/goban.rml
+++ b/data/gui/goban.rml
@@ -115,8 +115,8 @@
Game
Pass
-
Play once
Move
+
Kibitz move
Undo
diff --git a/data/shaders/fragment.glsl b/data/shaders/fragment.glsl
index a2ce492..bbd6ca6 100644
--- a/data/shaders/fragment.glsl
+++ b/data/shaders/fragment.glsl
@@ -24,6 +24,8 @@ uniform vec2 iResolution;
uniform int iStoneCount;
uniform int iBlackCapturedCount;
uniform int iWhiteCapturedCount;
+uniform int iBlackReservoirCount;
+uniform int iWhiteReservoirCount;
uniform float iTime;
layout(std140) uniform iStoneBlock{
vec4 iStones[MAXSTONES];
@@ -87,7 +89,7 @@ uniform float bowlRadius2;
struct Material {
int id;
vec3 diffuseAmbientSpecularWeight;
- float specularPower;
+ vec3 specularPower;
vec3 clrA;
vec3 clrB;
vec3 clrC;
@@ -104,6 +106,7 @@ struct Intersection {
vec4 dummy;
bool isBoard;
int uid;
+ int pid;
};
//const float gamma = 1.0;
const int idBack = -1;
@@ -122,27 +125,28 @@ const int idCapturedBlackStone = 11;
const int idCapturedWhiteStone = 12;
const int idLastBlackStone = 13;
const int idLastWhiteStone = 14;
-const int idCupBlack = 15;
-const int idCupWhite = 16;
-const int idBowlBlackStone = 17;
-const int idBowlWhiteStone = 18;
+const int idLidBlack = 15;
+const int idCupBlack = 16;
+const int idLidWhite = 17;
+const int idCupWhite = 18;
+const int idBowlBlackStone = 19;
+const int idBowlWhiteStone = 20;
const vec3 bgA = vec3(0.0, 0.0, 0.0);
const vec3 bgB = vec3(0.0, 0.0, 0.0);
-const Material mCupBlack = Material(idCupBlack, vec3(0.4, 0.6, 0.15), 16.0, vec3(0.65826, 0.528209, 0.238209), vec3(0.387763, 0.3289191, 0.12761), vec3(0.22005, 0.180002, 0.1244), 1.3);
-const Material mCupWhite = Material(idCupWhite, vec3(0.4, 0.6, 0.15), 16.0, vec3(0.45826, 0.428209, 0.238209), vec3(0.287763, 0.289191, 0.12761), vec3(0.12005, 0.120002, 0.085744), 1.3);
-const Material mBoard = Material(idBoard, 1.3*vec3(0.7, 0.3, 0.05), 42.0, vec3(0.93333, 0.713725, 0.38039), vec3(0.53333,0.313725,0.09039), vec3(0.7333,0.613725,0.19039), 1.5);
-const Material mTable = Material(idTable, vec3(1.2, 0.15, 0.0), 4.0, vec3(0.566,0.1196,0.0176), vec3(0.766,0.3196,0.2176), vec3(0.666,0.2196,0.1176), 0.0);
-const Material mWhite = Material(idWhiteStone, vec3(0.23, 0.73, 0.2), 42.0, vec3(0.96), vec3(0.86,0.82,0.87), vec3(0.93), 0.5);
-const Material mBlack = Material(idBlackStone, vec3(0.23, 0.83, 0.15), 28.0, vec3(0.08), vec3(0.04), vec3(0.10), 0.5);
-const Material mRed = Material(idLastBlackStone, vec3(0.3, 0.7, 0.25), 4.0, vec3(0.5, 0.0, 0.0), vec3(0.5, 0.0, 0.0), vec3(0.5, 0.0, 0.0), 0.0);
-const Material mBack = Material(idBack, vec3(0.0, 1.0, 0.0), 1.0, bgA, bgB, bgA, 0.0);
-const Material mGrid = Material(idGrid, vec3(1.5, 0.4, 0.15), 42.0, vec3(0.0),vec3(0.0), vec3(0.0), 0.0);
+const Material mCup = Material(idCupBlack, vec3(0.7, 0.15, 0.25), vec3(32.0), vec3(0.293333, 0.1713725, 0.038039), vec3(0.053333,0.0133725,0.029039), vec3(0.17333,0.1613725,0.089039), 1.5);
+const Material mBoard = Material(idBoard, vec3(0.7, 0.15, 0.05), vec3(42.0), vec3(0.93333, 0.813725, 0.38039), vec3(0.53333,0.413725,0.09039), vec3(0.7333,0.613725,0.19039), 1.5);
+const Material mTable = Material(idTable, vec3(1.0, 0.15, 0.0), vec3(4.0), vec3(0.566,0.0196,0.0176), vec3(0.766,0.1196,0.1176), vec3(0.666,0.0196,0.0176), 0.0);
+const Material mWhite = Material(idWhiteStone, vec3(0.53, 0.53, 0.2), vec3(32.0, 41.0, 2.0), vec3(0.96), vec3(0.96,0.91,0.97), vec3(0.93), 0.5);
+const Material mBlack = Material(idBlackStone, vec3(0.53, 0.53, 0.15), vec3(28.0), vec3(0.08), vec3(0.04), vec3(0.10), 0.5);
+const Material mRed = Material(idLastBlackStone, vec3(0.3, 0.15, 0.25), vec3(4.0), vec3(0.5, 0.0, 0.0), vec3(0.5, 0.0, 0.0), vec3(0.5, 0.0, 0.0), 0.0);
+const Material mBack = Material(idBack, vec3(0.0, 1.0, 0.0), vec3(1.0), bgA, bgB, bgA, 0.0);
+const Material mGrid = Material(idGrid, vec3(1.5, 0.15, 0.15), vec3(42.0), vec3(0.0),vec3(0.0), vec3(0.0), 0.0);
-uniform vec3 cc[2];
-const int maxCaptured = 32;
-uniform vec3 ddc[6 * maxCaptured];
+uniform vec3 cc[4];
+const int maxCaptured = 91;
+uniform vec4 ddc[2 * maxCaptured];
bool IntersectBox(in vec3 ro, in vec3 rd, in vec3 minimum, in vec3 maximum, out float start, out float final) {
vec3 ird = 1.0 / rd;
@@ -541,6 +545,32 @@ void updateResult(inout Intersection result[2], Intersection ret) {
}
}
+vec2 csg_union(in vec2 a, in vec2 b) {
+ if(b == noIntersection2)
+ return a;
+ if(a == noIntersection2)
+ return b;
+ return vec2(min(a.x, b.x), max(a.y, b.y));
+}
+
+vec2 csg_intersection(in vec2 a, in vec2 b) {
+ if(b == noIntersection2)
+ return b;
+ if(a == noIntersection2)
+ return a;
+ return vec2(max(a.x, b.x), min(a.y, b.y));
+}
+
+vec2 csg_difference(in vec2 a, in vec2 b) {
+ if(b == noIntersection2)
+ return a;
+ if(a == noIntersection2)
+ return a;
+ if(b.x > a.x)
+ return vec2(a.x, min(b.x, a.y));
+ return vec2(max(b.y, a.x), max(b.y, a.y));
+}
+
void castRay(in vec3 ro, in vec3 rd, out Intersection result[2]) {
Intersection ret;
@@ -551,6 +581,8 @@ void castRay(in vec3 ro, in vec3 rd, out Intersection result[2]) {
ret.p = vec3(-farClip);
ret.dummy = vec4(0.0);
ret.isBoard = false;
+ ret.pid = 0;
+ ret.uid = 0;
result[0] = result[1] = ret;
float tb, tb2;
@@ -763,46 +795,68 @@ void castRay(in vec3 ro, in vec3 rd, out Intersection result[2]) {
}
int isInCup = 0;
- for (int i = 0; i < 2; i++) {
- vec2 tc = vec2(dot(-ro - vec3(-0.1), nBoard), dot(bnx.xyz - vec3(2.0) - ro, nBoard)) / dot(rd, nBoard);
- vec2 ts = intersectionRaySphereR(ro, rd, cc[i], bowlRadius2*bowlRadius2);
- //vec2 tsx = intersectionRaySphereR(ro, rd, cc[i], 0.149);
- float firstx = tc.x;
- tc = vec2(min(tc.x, tc.y), max(tc.x, tc.y));
- bool between = ro.y < -0.3 && ro.y > bnx.y - legh;
- if (ts.x != noIntersection2.x && max(tc.x, ts.x) <= min(tc.y, ts.y)) {
- float rett = max(tc.x, ts.x);
- vec3 cc2 = cc[i];
- cc2.y = 0.1;
+ for (int i = 0; i < 4; i++) {
+ vec3 cc1 = cc[i];
+ cc1.y = bnx.y - legh + bowlRadius2 - 0.5* (bowlRadius2 - bowlRadius);
+ vec3 cc2 = cc1;
+ vec2 ts = intersectionRaySphereR(ro, rd, cc1, bowlRadius2*bowlRadius2);
+ float cuty = cc2.y + cc[i].y * bowlRadius;
+ vec2 tc = vec2(dot(-ro + vec3(cuty), nBoard), dot(bnx.xyz - vec3(10.0, legh, 10.0) - ro, nBoard)) / dot(rd, nBoard);
+ bool between = ro.y < cuty && ro.y > bnx.y - legh;
+ float ipy = ro.y + ts.x * rd.y;
+ if (((ro.y > cuty && max(tc.x, ts.x) <= min(tc.y, ts.y)) || (ro.y <= cuty && ipy< cuty)) && ts.x != noIntersection2.x){
+ float firstx = tc.x;
+ tc = vec2(min(tc.x, tc.y), max(tc.x, tc.y));
vec2 ts2 = intersectionRaySphereR(ro, rd, cc2, bowlRadius*bowlRadius);
- ret.t = vec2(!between && ts2.x < rett && ts2.y > rett ? ts2.y : rett, ts.y);
- ret.m = i == 0 ? idCupBlack : idCupWhite; //|ts2.x < rett && ts2.y > rett ?
+ ret.t = csg_difference(csg_intersection(tc, ts), ts2);
+ isInCup = i+1;
+ //if (ret.t.x == ts2.y && ts2.y != noIntersection2.x) {
+ //}
+ //float rett = max(tc.x, ts.x);
+ //ret.t = vec2(!between && ts2.x < rett && ts2.y > rett ? ts2.y : rett, ts.y);
+ ret.m = i < 2 ? (i == 0 ? idLidBlack : idLidWhite) : (i == 2 ? idCupBlack: idCupWhite); //|ts2.x < rett && ts2.y > rett ?
ret.p = ro + ret.t.x*rd;
- vec3 nn = (ts2.x > rett || ts2.y < rett) && tc.x > ts.x ? nBoard : ts2.x < rett && ts2.y > rett ? -normalize(ret.p - cc2) : normalize(ret.p - cc[i]);
- float d1 = distanceRaySphere(ro, rd, cc[i], bowlRadius2);
+ float ln = cc2.y - cuty;
+ float r1 = sqrt(bowlRadius*bowlRadius - ln*ln);
+ float r2 = sqrt(bowlRadius2*bowlRadius2 - ln*ln);
+ float alpha = distance(ret.p.xz, cc2.xz) - 0.5*(r2 + r1);
+ //vec3 nn = ret.t.x == tc.x ? nBoard : ret.t.x == ts2.y ?
+ // normalize(mix(-normalize(ret.p - cc2), nBoard, 1.0/exp(-150.0*alpha)))
+ // : normalize(mix(normalize(ret.p - cc1), nBoard, 1.0/exp(-150.0*alpha)));//(ts2.x > rett || ts2.y < rett) && tc.x > ts.x ? nBoard : ts2.x < rett && ts2.y > rett ? -normalize(ret.p - cc2) : normalize(ret.p - cc1);
+ vec3 nn = ret.t.x == tc.x ? nBoard : ret.t.x == ts2.y ? -normalize(ret.p - cc2) : normalize(ret.p - cc1);
+ //(ts2.x > rett || ts2.y < rett) && tc.x > ts.x ? nBoard : ts2.x < rett && ts2.y > rett ? -normalize(ret.p - cc2) : normalize(ret.p - cc1);
+ /*vec3 nn = ret.t.x == tc.x ? nBoard : ret.t.x == ts2.y ? -normalize(ret.p - cc2) : normalize(ret.p - cc1);
+ if(ret.t.x == tc.x) {
+ if(alpha > 0.0) {
+ nn = normalize(mix(-normalize(ret.p - cc2), nn, 1.0/exp(25.0*abs(alpha))));
+ } else if ( alpha < 0.0) {
+ nn = normalize(mix(normalize(ret.p - cc1), nn, 1.0/exp(25.0*abs(alpha))));
+ }
+ }*/
+ float d1 = distanceRaySphere(ro, rd, cc1, bowlRadius2);
vec3 q22, q23;
- float d2 = distanceRayCircle(ro, rd, ro + tc.x*rd, vec2(farClip), cc2, bowlRadius, q22).y;
- float ln = distance(cc[i], cc2);
- float d3 = distanceRayCircle(ro, rd, ro + tc.x*rd, vec2(farClip), cc2, sqrt(bowlRadius2*bowlRadius2 - ln*ln), q23).y;
+ vec3 cc3 = cc2;
+ cc3.y = cuty;
+ float d2 = distanceRayCircle(ro, rd, ro + tc.x*rd, vec2(farClip), cc3, r1, q22).y;
+ float d3 = distanceRayCircle(ro, rd, ro + tc.x*rd, vec2(farClip), cc3, r2, q23).y;
float md = d2;
bool solid = true;
float find = -d3;
ret.n = nn;
- ret.d = -farClip;
+ //ret.d = -farClip;//-farClip;
float dot1 = dot(ret.p, rd);
- float dot2 = dot(cc[i], rd);
+ float dot2 = dot(cc1, rd);
ret.d = -farClip;
bool exter = d2 < -d3;
ret.d = max(d2 > -boardaa ? d2 : -farClip, d3 < boardaa ? -d3 : -farClip);
- if (ts2.x != noIntersection2.x)
- isInCup = ret.p.x < 0.0 ? 1 : 2;
- if (d1 < 0.0 && ret.d < 0.0 && ro.y > -0.3) {
- ret.d = max(d1, ret.d);
- ret.t = tc;//vec2(exter ? max(tc.x, ts.x) : min(max(ts2.x < farClip ? ts2.y: -farClip, tc.x), ts.y));
+ if (d1 < 0.0 && ret.d < 0.0 && ro.y > bnx.y - legh) {
+ //ret.d = max(d1, ret.d);
+ //ret.t = tc;
ret.p = ro + ret.t.x*rd;
- ret.n = nBoard; //normalize(mix(nBoard, nn, clamp(abs(d2)/boardaa,0.0,1.0))); //;//exter ? normalize(ret.p - cc[i]) : normalize(cc2 - ret.p);
+ ret.n = nBoard;
updateResult(result, ret);
+ ret.pid = isInCup;
ret.d = farClip;
if (!exter) {
ret.d = -farClip;
@@ -810,21 +864,21 @@ void castRay(in vec3 ro, in vec3 rd, out Intersection result[2]) {
ret.p = ro + ret.t.x*rd;
ret.n = normalize(cc2 - ret.p);
}
- else if (dot1 - dot2 <= 0.0 && d1 < -0.5*boardaa) {
+ else if (dot1 - dot2 < 0.0 && d1 < -0.5*boardaa) {
ret.d = -farClip;
ret.t = vec2(tc.x + 0.001);
ret.p = ro + ret.t.x*rd;
- ret.n = normalize(ret.p - cc[i]);
+ ret.n = normalize(ret.p - cc1);
}
}
else {
- if (tc.x < ts.x && ts.x < farClip && ts.x > 0.0) {
+ if (tc.x - 0.02 < ts.x && ts.x < farClip && ts.x > 0.0) {
ret.d = d1;
- ret.t = vec2(ts.x);
+ ret.t = vec2(ts.x - 0.01);
ret.p = ro + ret.t.x*rd;
- ret.n = normalize(ret.p - cc[i]);
+ ret.n = normalize(ret.p - cc1);
}
- else if (ts2.y > tc.x && ts2.x < farClip && ts2.y > -0.3) {
+ else if (ts2.y > tc.x && ts2.x < farClip && ts2.y > bnx.y - legh) {
ret.d = -farClip;
ret.t = vec2(ts2.y);
ret.p = ro + ret.t.x*rd;
@@ -839,23 +893,40 @@ void castRay(in vec3 ro, in vec3 rd, out Intersection result[2]) {
int si = 0;
int ei = 0;
- if (isInCup == 1) { si = 0; ei = min(maxCaptured, iBlackCapturedCount); }
- else if (isInCup == 2){ si = maxCaptured; ei = maxCaptured + min(maxCaptured, iWhiteCapturedCount); }
+ vec3 cci;
+ cci = cc[isInCup - 1];
+ if (isInCup == 2 || isInCup ==4) {
+ si = 0;
+ if(isInCup == 2)
+ ei = min(maxCaptured, iWhiteCapturedCount);
+ else
+ ei = min(maxCaptured, iBlackReservoirCount);
+ }
+ else if (isInCup == 1 || isInCup == 3){
+ si = maxCaptured;
+ if(isInCup == 1)
+ ei = maxCaptured + min(maxCaptured, iBlackCapturedCount);
+ else
+ ei = maxCaptured + min(maxCaptured, iWhiteReservoirCount);
+ }
for (int i = si; i < ei; ++i) {
- vec3 ddc = ddc[i];
+ vec4 ddc = ddc[i];
+ ddc.xz += cci.xz;
+ ddc.y += bnx.y - legh + bowlRadius2 - bowlRadius;
int mm0;
vec4 ret0;
float tt2;
- if (intersectionRayStone(ro, rd, ddc, result[1].t.x, ret0, tt2)) {
+ if (intersectionRayStone(ro, rd, ddc.xyz, result[1].t.x, ret0, tt2)) {
vec3 ip = ro + rd*ret0.w;
- int mm0 = i < maxCaptured ? idBowlBlackStone : idBowlWhiteStone;
- ret.dummy = vec4(ddc, 0.0);
+ int mm0 = (i < maxCaptured != (isInCup < 3)) ? idBowlBlackStone : idBowlWhiteStone;
+ ret.dummy = ddc;
ret.t = vec2(ret0.w, tt2);
ret.m = mm0;
ret.d = -farClip;
ret.n = ret0.xyz;
ret.p = ip;
- ret.uid = i;
+ ret.uid = i+ (isInCup - 1)*maxCaptured;
+ ret.pid = isInCup;
if (mm0 > idBack) {
// updateResult(result, ret);
@@ -951,7 +1022,7 @@ void castRay(in vec3 ro, in vec3 rd, out Intersection result[2]) {
//finalizeStoneIntersection(ro, rd, result, 1);
}
-vec2 softshadow(in vec3 pos, in vec3 nor, const vec3 lig, const float ldia, int m, bool ao, int uid){
+vec2 softshadow(in vec3 pos, in vec3 nor, const vec3 lig, const float ldia, int m, bool ao, int uid, int pid) {
vec2 ret = vec2(1.0);
bool isBoard = m == idBoard || m == idLeg1 || m == idLeg2 || m == idLeg3 || m == idLeg4 || m == idGrid;
if (isBoard && pos.y > h) return ret;
@@ -980,28 +1051,33 @@ vec2 softshadow(in vec3 pos, in vec3 nor, const vec3 lig, const float ldia, int
ret.x *= mx;
}
if (m == idTable) {
- vec3 ddpos = (pos.x < 0.0 ? cc[0] : cc[1]) - pos;
- float ln = length(ddpos);
- vec3 ldir = ddpos;
- float res = dot(lig - pos, nBoard) / dot(ldir, nBoard);
- vec3 ip = pos + res*ldir;
- vec2 rR = vec2(bowlRadius2*length(ip - pos) / ln, ldia);
- vec2 rR2 = rR*rR;
- float A = PI*min(rR2.x, rR2.y);
- float d = length(ip - lig);
- vec4 rmR = vec4(rR + rR.yx, rR - rR.yx);
- if (d > abs(rmR.z) && d < rmR.x) {
- vec2 rrRR = rR2.xy - rR2.yx;
- vec2 d12 = 0.5*(vec2(d) + rrRR / d);
- float dt = (-d + rmR.x)*(d + rmR.z)*(d + rmR.w)*(d + rmR.x);
- A = dot(rR2, acos(d12 / rR)) - 0.5*sqrt(dt);
- }
- else if (d > rmR.x) {
- A = 0.0;
+ for(int j = 0; j <= 2; j += 2) {
+ vec3 cci = (pos.x < 0.0 ? cc[j+0] : cc[j+1]);
+ float yy = bnx.y - legh + bowlRadius2 - 0.5* (bowlRadius2 - bowlRadius);
+ cci.y = yy + cci.y * bowlRadius;
+ vec3 ddpos = cci - pos;
+ float ln = length(ddpos);
+ vec3 ldir = ddpos;
+ float res = dot(lig - pos, nBoard) / dot(ldir, nBoard);
+ vec3 ip = pos + res*ldir;
+ vec2 rR = vec2(bowlRadius2*length(ip - pos) / ln, ldia);
+ vec2 rR2 = rR*rR;
+ float A = PI*min(rR2.x, rR2.y);
+ float d = length(ip - lig);
+ vec4 rmR = vec4(rR + rR.yx, rR - rR.yx);
+ if (d > abs(rmR.z) && d < rmR.x) {
+ vec2 rrRR = rR2.xy - rR2.yx;
+ vec2 d12 = 0.5*(vec2(d) + rrRR / d);
+ float dt = (-d + rmR.x)*(d + rmR.z)*(d + rmR.w)*(d + rmR.x);
+ A = dot(rR2, acos(d12 / rR)) - 0.5*sqrt(dt);
+ }
+ else if (d > rmR.x) {
+ A = 0.0;
+ }
+ ret.x *= 1.0 - A / (PI*ldia2);
}
- ret.x *= 1.0 - A / (PI*ldia2);
}
- if ((m == idCupWhite || m == idCupBlack) || ((m == idLeg1 || m == idLeg2 || m == idLeg3 || m == idLeg4 || m == idBoard) && pos.y < -0.00001)) {
+ if ((m == idCupWhite || m == idCupBlack || m == idLidWhite || m == idLidBlack) || ((m == idLeg1 || m == idLeg2 || m == idLeg3 || m == idLeg4 || m == idBoard) && pos.y < -0.00001)) {
vec3 u = normalize(cross(nor, nBoard));
vec3 v = cross(nor, u);
vec3 ip = pos + v*dot(lpos - pos, -nBoard) / dot(v, -nBoard);
@@ -1010,7 +1086,11 @@ vec2 softshadow(in vec3 pos, in vec3 nor, const vec3 lig, const float ldia, int
float A = d < ldia ? 0.5*ldia2*(phi - sin(phi)) / (PI*ldia2) : 0.0;
//ret.x *= dot(lpos - pos, nor) > 0.0 ? 1.0 - A : A;
int i = m - idLeg1;
- vec2 xz = m == idCupBlack || m == idCupWhite ? (pos.x < 0.0 ? cc[0].xz : cc[1].xz) : m == idBoard ? vec2(0.0) : vec2(1 - 2 * (i & 1), 1 - 2 * ((i >> 1) & 1))*(bnx.xx + vec2(legh));
+ vec3 cci;
+ if(pid > 0) {
+ cci = cc[pid - 1];
+ }
+ vec2 xz = (m == idCupBlack || m == idCupWhite || m == idLidWhite || m == idLidBlack) ? cci.xz : m == idBoard ? vec2(0.0) : vec2(1 - 2 * (i & 1), 1 - 2 * ((i >> 1) & 1))*(bnx.xx + vec2(legh));
phi = PI - abs(acos(dot(v.xz, normalize(pos.xz - xz))));
if (distance(pos.xz + nor.xz, xz) > distance(pos.xz - nor.xz, xz) || m == idBoard) {
ret.y *= phi / PI;
@@ -1075,14 +1155,32 @@ vec2 softshadow(in vec3 pos, in vec3 nor, const vec3 lig, const float ldia, int
}
}
- if ((m == idCupBlack || m == idCupWhite || (m == idBowlBlackStone || m == idBowlWhiteStone)) && abs(pos.x) > 1.0) {
- int i = pos.x < 0.0 ? 0 : 1;
+ if ((m == idCupBlack || m == idCupWhite || m == idLidWhite || m == idLidBlack || m == idBowlBlackStone || m == idBowlWhiteStone) && abs(pos.x) > 1.0) {
+ int isInCup = -1;
+ if(pid > 0) {
+ isInCup = pid;
+ }
int si = 0; int ei = 0;
- if (i == 0) { si = 0; ei = min(maxCaptured, iBlackCapturedCount); }
- else if (i == 1){ si = maxCaptured; ei = maxCaptured + min(maxCaptured, iWhiteCapturedCount); }
+ if (isInCup == 2 || isInCup ==4) {
+ si = 0;
+ if(isInCup == 2)
+ ei = min(maxCaptured, iWhiteCapturedCount);
+ else
+ ei = min(maxCaptured, iBlackReservoirCount);
+ }
+ else if (isInCup == 1 || isInCup == 3){
+ si = maxCaptured;
+ if(isInCup == 1)
+ ei = maxCaptured + min(maxCaptured, iBlackCapturedCount);
+ else
+ ei = maxCaptured + min(maxCaptured, iWhiteReservoirCount);
+ }
for (int j = si; j < ei; ++j) {
- if ((m == idCupBlack || m == idCupWhite || uid != j) && pos.y < ddc[j].y - 0.01*h){
- vec3 ddpos = ddc[j] - pos;
+ vec4 ddcj = ddc[j];
+ ddcj.xz += cc[isInCup-1].xz;
+ ddcj.y += bnx.y - legh + bowlRadius2 - bowlRadius;
+ if ((m == idCupBlack || m == idCupWhite || m == idLidWhite || m == idLidBlack) || ((m == idBowlBlackStone || m == idBowlWhiteStone) && uid != j && pos.y < ddcj.y - 0.01*h)){
+ vec3 ddpos = ddcj.xyz - pos;
float ln = length(ddpos);
vec3 ldir = ddpos;
float res = dot(lig - pos, nBoard) / dot(ldir, nBoard);
@@ -1103,11 +1201,11 @@ vec2 softshadow(in vec3 pos, in vec3 nor, const vec3 lig, const float ldia, int
}
ret.x *= 1.0 - A / (PI*ldia2);
}
- else if ((m == idBowlBlackStone || m == idBowlWhiteStone) && (pos.y < ddc[j].y - 0.01*h || uid == j)) {
+ /*else if ((m == idBowlBlackStone || m == idBowlWhiteStone) && (pos.y < ddcj.y + 0.01*h || uid == j)) {
vec3 u = normalize(cross(nor, nBoard));
vec3 v = cross(nor, u);
- ret.y *= min(1.0, 1.0 - abs(acos(dot(v.xz, normalize(pos.xz - ddc[j].xz)))) / PI);
- }
+ ret.y *= min(1.0, 1.0 - abs(acos(dot(v.xz, normalize(pos.xz - ddcj.xz)))) / PI);
+ }*/
}
}
}
@@ -1123,10 +1221,16 @@ Material getMaterial(int m) {
ret = mBoard;
}
else if (m == idCupBlack) {
- ret = mBoard;
+ ret = mCup;
}
else if (m == idCupWhite) {
- ret = mBoard;
+ ret = mCup;
+ }
+ else if (m == idLidBlack) {
+ ret = mCup;
+ }
+ else if (m == idLidWhite) {
+ ret = mCup;
}
else if (m == idWhiteStone || m == idWhiteArea || m == idCapturedWhiteStone || m == idBowlWhiteStone) {
ret = mWhite;
@@ -1146,7 +1250,7 @@ Material getMaterial(int m) {
return ret;
}
-Material getMaterialColor(in Intersection ip, out vec3 mcol, in vec3 rd, in vec3 ro, out vec3 nn) {
+Material getMaterialColor(in Intersection ip, out vec4 mcol, in vec3 rd, in vec3 ro, out vec3 nn) {
Material mat = getMaterial(ip.m);
Material m0 = mat;//;at = mBoard;// getMaterial(idBoard);//ip.m
bool noisy = false;
@@ -1160,7 +1264,7 @@ Material getMaterialColor(in Intersection ip, out vec3 mcol, in vec3 rd, in vec3
smult1 = 0.0;
smult2 = 0.0;
smult3 = 1.0;
- mcol = m0.clrA;
+ mcol.xyz = m0.clrA;
vec3 mcolb = m0.clrB;
vec3 mcolc = m0.clrC;
vec3 flr = ip.dummy.xyz;
@@ -1169,7 +1273,7 @@ Material getMaterialColor(in Intersection ip, out vec3 mcol, in vec3 rd, in vec3
float degrade = (1.0 + floor(length(ro) / 3.0));
vec2 xz;
xz = scrd.xz;
- if (mat.id == mBoard.id || mat.id == mCupBlack.id || mat.id == mCupWhite.id) {
+ if (mat.id == mBoard.id || mat.id == mCup.id) {
scoord = 16.0*vec3(xz.x,scrd.y,xz.y) + vec3(0.0, 0.25, 0.0);
scoord.x = 2.0*length(scoord.xy);
scoord.z = 2.0*scoord.y;
@@ -1177,8 +1281,8 @@ Material getMaterialColor(in Intersection ip, out vec3 mcol, in vec3 rd, in vec3
scoord.xyz = 0.1*vec3(length(scoord.yz));
noisy = true;
scrd = scoord;
- mixmult = 1.0;
- mixnorm = 0.015;
+ mixmult = 1.0;
+ mixnorm = 0.01;
}
else if (mat.id == mGrid.id) {
scoord = 350.0*scrd;
@@ -1233,13 +1337,13 @@ Material getMaterialColor(in Intersection ip, out vec3 mcol, in vec3 rd, in vec3
float alpha = 3.1415926/4.0;
if (!third && ab) //;(a &&!b) || (!a && b))
{
- mcol = mix(mTable.clrA, mTable.clrC, max(c05b, c05a));
+ mcol.xyz = mix(mTable.clrA, mTable.clrC, max(c05b, c05a));
}
else if (!third){
- mcol = mix(mTable.clrB, mTable.clrC, max(c05b, c05a));
+ mcol.xyz = mix(mTable.clrB, mTable.clrC, max(c05b, c05a));
}
else {
- mcol = mTable.clrC;
+ mcol.xyz = mTable.clrC;
alpha = 0.0;
}
float cosa = cos(alpha);
@@ -1251,9 +1355,9 @@ Material getMaterialColor(in Intersection ip, out vec3 mcol, in vec3 rd, in vec3
noisy = true;
const float al = 0.15;
float mixt = exp(-0.35*max(0.0, length(ip.p)));
- mcolb = mixt*(mcol + (al)*(vec3(1.0) - mcol));
- mcolc = mixt*((1.0 - al)*mcol);
- mcol *= mixt;
+ mcolb = mixt*(mcol.xyz + (al)*(vec3(1.0) - mcol.xyz));
+ mcolc = mixt*((1.0 - al)*mcol.xyz);
+ mcol.xyz *= mixt;
mixmult = 0.1;
mixnorm = 0.0;
}
@@ -1265,7 +1369,7 @@ Material getMaterialColor(in Intersection ip, out vec3 mcol, in vec3 rd, in vec3
rnd = snoise(scrd, grad);
rnd2 = snoise(scrd2+mixmult*grad, grad2);
//}
- if (mat.id == mBoard.id || mat.id == mCupBlack.id || mat.id == mCupWhite.id) {
+ if (mat.id == mBoard.id || mat.id == mCup.id) {
float w1 = 3.0*length(scoord.yx - 0.5*vec2(1.57 + 3.1415*rnd));
float w2 = 0.1*(scoord.x + scoord.z);
smult1 = mix(clamp(abs(rnd),0.0,1.0), 1.0, 0.01)*(clamp(0.25*(sin(grad.x)), 0.0, 1.0));
@@ -1279,35 +1383,34 @@ Material getMaterialColor(in Intersection ip, out vec3 mcol, in vec3 rd, in vec3
smult3 = 0.5;//clamp(abs(grad.z),0.0,1.0);
mixmult = 0.0;
}
- mcol = mix(mix(mcol, mcolb, smult2), mix(mcol, mcolc, 1.0 - smult2), smult1);
+ mcol.xyz = mix(mix(mcol.xyz, mcolb, smult2), mix(mcol.xyz, mcolc, 1.0 - smult2), smult1);
+ mcol.w = mix(mix(mat.specularPower.x, mat.specularPower.y, smult2), mix(mat.specularPower.x, mat.specularPower.z, 1.0 - smult2), smult1);
nn = normalize(mix(ip.n, grad2, mixnorm));
//nn = ip.n;
return mat;
}
-vec3 shading(in vec3 ro, in vec3 rd, in Intersection ip, const Material mat, vec3 col){
+vec3 shading(in vec3 ro, in vec3 rd, in Intersection ip, const Material mat, vec4 col){
vec3 ret;
if (mat.id == mBack.id) {
ret = mat.clrA;
}
else {
- //vec3 smult0 = clamp(abs(col - mat.clrB) / abs(mat.clrA.x - mat.clrB), 0.0, 1.0);
- //float smult = 0.333 * dot(smult0, vec3(1.0));
vec3 nn = ip.n;
vec3 ref = reflect(rd, nn);
vec3 lig = normalize(lpos - ip.p);
vec3 lig2 = normalize(lpos2 - ip.p);
vec3 lig3 = normalize(lpos3 - ip.p);
- vec2 shadow = pow(softshadow(ip.p, ip.n, lpos, ldia, ip.m, false, ip.uid), vec2(1.0, 0.25));//0.6
+ vec2 shadow = pow(softshadow(ip.p, ip.n, lpos, ldia, ip.m, false, ip.uid, ip.pid), vec2(1.0, 0.25));//0.6
//shadow += 0.4*pow(softshadow(ip.p, ip.n, lpos2, ldia, ip.m, false, ip.uid), vec2(1.0,0.25));
float nny = 0.5 + 0.5*nn.y;
float adsy = dot(vec3(0.6,0.3,0.3), clamp(vec3(dot(nn, lig), dot(nn, lig2), dot(nn, lig3)),0.0,1.0));
vec4 pws = clamp(vec4(dot(ref, lig), dot(ref, lig2), dot(ref, lig3), dot(ref, lig3)), 0.0, 1.0);
- vec3 cupsab = ip.m == idBowlBlackStone || ip.m == idBowlWhiteStone ? vec3(0.125,0.9,0.25) : vec3(0.125,1.0,0.5);
- vec3 pwr = pow(pws.xyz, mat.specularPower*cupsab);
+ vec3 cupsab = vec3(1.0);//ip.m == idBowlBlackStone || ip.m == idBowlWhiteStone ? vec3(0.125,0.9,0.25) : vec3(0.125,1.0,0.5);
+ vec3 pwr = pow(pws.xyz, col.w*cupsab);
vec3 score = mat.diffuseAmbientSpecularWeight * vec3(adsy * shadow.x, shadow.y,shadow.y*(0.25*pwr.x + pwr.y + pwr.z));
- ret = (score.x + score.y)*col + score.z;
+ ret = (score.x + score.y)*col.xyz + score.z;
}
ret = pow(ret, gamma*exp(contrast*(vec3(0.5) - ret)));
return ret;
@@ -1324,7 +1427,8 @@ vec3 render(in vec3 ro, in vec3 rd, in vec3 bg)
float alpha1 = smoothstep(boardaa, 0.0, -ret[0].d);
float alpha2 = smoothstep(boardaa, 0.0, -ret[1].d);
- vec3 col, mcol;
+ vec3 col;
+ vec4 mcol;
Material mat;
vec3 nn;
mat = getMaterialColor(ret[0], mcol, rd, ro, nn);
@@ -1335,7 +1439,7 @@ vec3 render(in vec3 ro, in vec3 rd, in vec3 bg)
if (ret[0].m == idBoard) {
float alpha3 = smoothstep(boardaa, 0.0, -ret[0].d2);
if(alpha3 > 0.0) {
- col = mix(col, shading(ro, rd, ret[0], mGrid, mGrid.clrA), alpha3);
+ col = mix(col, shading(ro, rd, ret[0], mGrid, vec4(mGrid.clrA, mGrid.specularPower.x)), alpha3);
}
}
col *= (1.0-w);
@@ -1350,7 +1454,7 @@ vec3 render(in vec3 ro, in vec3 rd, in vec3 bg)
if (ret[1].m == idBoard) {
float alpha3 = smoothstep(boardaa, 0.0, -ret[1].d2);
if(alpha3 > 0.0) {
- vec3 col3 = shading(ro, rd, ret[1], mGrid, mGrid.clrA);
+ vec3 col3 = shading(ro, rd, ret[1], mGrid, vec4(mGrid.clrA, mGrid.specularPower.x));
col1 = mix(col1, col3, alpha3);
}
col += alpha1*col1;
diff --git a/src/Board.h b/src/Board.h
index e82395d..56033c9 100644
--- a/src/Board.h
+++ b/src/Board.h
@@ -83,7 +83,7 @@ class Move {
public:
- enum Special { INVALID, INTERRUPT, NORMAL, PASS, UNDO, RESIGN };
+ enum Special { INVALID, INTERRUPT, NORMAL, PASS, UNDO, RESIGN, KIBITZED};
Move(): spec(INVALID), col(Color::EMPTY) {}
@@ -93,7 +93,7 @@ class Move {
: spec(NORMAL), pos(pos), col(col)
{ }
- operator bool() const { return spec != INVALID && spec != INTERRUPT; }
+ operator bool() const { return spec != INVALID && spec != INTERRUPT && spec != KIBITZED; }
operator Position() const { return pos; }
operator Color() const { return col; }
@@ -221,6 +221,10 @@ class Board
void setRandomStoneRotation() {
randomStoneRotation = 3.1415f * udist(generator);
}
+
+ double getRandomStoneRotation() {
+ return 3.1415f * udist(generator);
+ }
private:
inline int ord(const Position& p) const {
diff --git a/src/ElementGame.cpp b/src/ElementGame.cpp
index 14686dd..afc9ca5 100644
--- a/src/ElementGame.cpp
+++ b/src/ElementGame.cpp
@@ -172,7 +172,7 @@ void ElementGame::OnUpdate()
}
- std::string cmd(isOver ? "New" : !isRunning ? "Play" : "Pass");
+ std::string cmd(isOver ? "Clear" : !isRunning ? "Start" : "Pass");
model.state.cmd = cmd;
if (view.state.cmd != model.state.cmd) {
Rocket::Core::Element* cmdPass = context->GetDocument("game_window")->GetElementById("cmdPass");
@@ -217,6 +217,12 @@ void ElementGame::OnUpdate()
view.state.capturedWhite = model.state.capturedWhite;
view.state.reason = model.state.reason;
}
+ if(view.state.reservoirBlack != model.state.reservoirBlack
+ || view.state.reservoirWhite != model.state.reservoirWhite) {
+ view.state.reservoirBlack = model.state.reservoirBlack;
+ view.state.reservoirWhite = model.state.reservoirWhite;
+ requestRepaint();
+ }
if (view.state.handicap != model.state.handicap) {
Rocket::Core::Element* hand = context->GetDocument("game_window")->GetElementById("lblHandicap");
if (hand != NULL) {
diff --git a/src/GameState.h b/src/GameState.h
index 5bc287f..4d96821 100644
--- a/src/GameState.h
+++ b/src/GameState.h
@@ -9,6 +9,7 @@ class GameState {
std::string black;
std::string white;
int capturedBlack, capturedWhite;
+ int reservoirBlack, reservoirWhite;
float komi;
int handicap;
float result;
@@ -24,6 +25,7 @@ class GameState {
Message msg;
GameState(): colorToMove(Color::BLACK), black(""), white(""), capturedBlack(0), capturedWhite(0),
+ reservoirBlack(32), reservoirWhite(32),
komi(0.5f), handicap(0), result(0.0f), cmd("xxx"), msg(PAUSED),
reason(NOREASON), adata(), metricsReady(false), showTerritory(false), showOverlay(false),
holdsStone(false), dirty(true)
diff --git a/src/GameThread.cpp b/src/GameThread.cpp
index 8ebb171..41c5607 100644
--- a/src/GameThread.cpp
+++ b/src/GameThread.cpp
@@ -4,7 +4,7 @@
GameThread::GameThread(GobanModel &m) :
model(m), thread(nullptr), interruptRequested(false), hasThreadRunning(false),
- playerToMove(0), human(0), sgf(0), coach(0), numPlayers(0), activePlayer({0, 0})
+ playerToMove(0), human(0), sgf(0), coach(0), kibitz(0), numPlayers(0), activePlayer({0, 0})
{
}
@@ -41,6 +41,14 @@ Engine* GameThread::currentCoach() {
}
return 0;
}
+
+Engine* GameThread::currentKibitz() {
+ for(auto eit = engines.begin(); eit != engines.end(); ++eit) {
+ if((*eit)->hasRole(Player::KIBITZ)) return *eit;
+ }
+ return 0;
+}
+
Player* GameThread::currentPlayer() {
int roleToMove = model.state.colorToMove == Color::BLACK ? Player::BLACK : Player::WHITE;
for(auto pit = players.begin(); pit != players.end(); ++pit) {
@@ -222,11 +230,13 @@ void GameThread::gameLoop() {
interruptRequested = false;
while (model && !interruptRequested) {
Engine* coach = currentCoach();
+ Engine* kibitz = currentKibitz();
Player* player = currentPlayer();
std::unique_lock lock(playerMutex, std::defer_lock);
bool locked = false;
if(coach && player && !interruptRequested) {
bool success = false;
+ bool kibitzed = false;
bool doubleUndo = false;
playerToMove = player;
if(!player->isTypeOf(Player::HUMAN)){
@@ -237,6 +247,10 @@ void GameThread::gameLoop() {
player->suggestMove(Move(Move::INVALID, model.state.colorToMove));
//blocking wait for move
Move move = player->genmove(model.state.colorToMove);
+ if(move == Move::KIBITZED) {
+ move = kibitz->genmove(model.state.colorToMove);
+ kibitzed = true;
+ }
spdlog::debug("MOVE to {}, valid = {}", move.toString(), move);
playerToMove = 0;
if(player->isTypeOf(Player::HUMAN)){
@@ -262,6 +276,7 @@ void GameThread::gameLoop() {
else if (move) {
// coach plays
success = player == coach
+ || (kibitzed && kibitz == coach)
|| move == Move::RESIGN
|| coach->play(move);
}
@@ -270,7 +285,7 @@ void GameThread::gameLoop() {
if (!(move == Move::RESIGN)) {
for (auto pit = players.begin(); pit != players.end(); ++pit) {
Player *p = *pit;
- if (p != reinterpret_cast(coach) && p != player) {
+ if (p != reinterpret_cast(coach) && p != player && (!kibitzed || p != kibitz)) {
spdlog::debug("DEBUG play iter");
if (move == Move::UNDO) {
undo(p, doubleUndo);
@@ -328,10 +343,17 @@ void GameThread::playLocalMove(const Move& move) {
if(playerToMove) playerToMove->suggestMove(move);
}
+void GameThread::playKibitzMove() {
+ std::unique_lock lock(playerMutex);
+ Move kibitzed(Move::KIBITZED, model.state.colorToMove);
+ if(playerToMove) playerToMove->suggestMove(kibitzed);
+}
+
void GameThread::loadEngines(const std::shared_ptr config) {
auto bots = config->data.find("bots");
if(bots != config->data.end()) {
bool hasCoach(false);
+ bool hasKibitz(false);
for(auto it = bots->begin(); it != bots->end(); ++it) {
auto enabled = it->value("enabled", 1);
if(enabled) {
@@ -340,6 +362,7 @@ void GameThread::loadEngines(const std::shared_ptr config) {
auto command = it->value("command", "");
auto parameters = it->value("parameters", "");
auto main = it->value("main", 0);
+ auto kibitz = it->value("kibitz", 0);
auto messages = it->value("messages", nlohmann::json::array());
int role = Player::SPECTATOR;
@@ -367,13 +390,32 @@ void GameThread::loadEngines(const std::shared_ptr config) {
players[coach]->getName());
}
}
-
+ if (kibitz) {
+ if(!hasKibitz) {
+ role |= Player::KIBITZ;
+ hasKibitz = true;
+ kibitz = id;
+ spdlog::info("Setting [{}] engine as trusted kibitz.",
+ players[id]->getName());
+ } else {
+ spdlog::warn("Ignoring kibitz flag for [{}] engine, kibitz has already been set to [{}].",
+ players[id]->getName(),
+ players[coach]->getName());
+ }
+ }
setRole(id, role, true);
}
}
}
+ if(!hasKibitz) {
+ kibitz = coach;
+ spdlog::info("No kibitz set. Defaulting to [{}] coach engine.",
+ players[kibitz]->getName());
+ players[coach]->setRole(players[coach]->getRole() | Player::KIBITZ);
+ }
}
- sgf = -1; //addPlayer(new SgfPlayer("SGF Record", "./problems/alphago-2016/3/13/Tictactoe.sgf"));
+
+ sgf = -1;
human = addPlayer(new LocalHumanPlayer("Human"));
diff --git a/src/GameThread.h b/src/GameThread.h
index 113ca01..4a1da51 100644
--- a/src/GameThread.h
+++ b/src/GameThread.h
@@ -28,6 +28,7 @@ class GameThread
size_t addPlayer(Player* player);
Engine* currentCoach();
+ Engine* currentKibitz();
Player* currentPlayer();
@@ -52,6 +53,7 @@ class GameThread
bool humanToMove();
void playLocalMove(const Move& move);
+ void playKibitzMove();
void loadEngines(const std::shared_ptr config);
@@ -82,7 +84,7 @@ class GameThread
std::mutex mutex2;
volatile bool interruptRequested, hasThreadRunning;
Player* playerToMove;
- std::size_t human, sgf, coach;
+ std::size_t human, sgf, coach, kibitz;
std::size_t numPlayers;
std::array activePlayer;
std::mutex playerMutex;
diff --git a/src/GobanControl.cpp b/src/GobanControl.cpp
index 66e9b71..025d209 100644
--- a/src/GobanControl.cpp
+++ b/src/GobanControl.cpp
@@ -45,6 +45,10 @@ void GobanControl::mouseClick(int button, int state, int x, int y) {
}
else {
model.state.holdsStone = true;
+ if(model.state.colorToMove == Color::BLACK)
+ model.state.reservoirBlack -= 1;
+ else
+ model.state.reservoirWhite -= 1;
view.requestRepaint(GobanView::UPDATE_STONES);
}
}
@@ -102,6 +106,10 @@ bool GobanControl::command(const std::string& cmd) {
view.toggleOverlay();
view.requestRepaint();
}
+ else if (cmd == "play once") {
+ engine.playKibitzMove();
+ view.requestRepaint();
+ }
else if (cmd == "play pass") {
bool playNow = !firstGame;
if (model.isGameOver()) {
diff --git a/src/GobanModel.cpp b/src/GobanModel.cpp
index 6466d3b..3a39427 100644
--- a/src/GobanModel.cpp
+++ b/src/GobanModel.cpp
@@ -20,11 +20,13 @@ void GobanModel::onBoardSized(int boardSize) {
state = GameState();
+ state.reservoirBlack = state.reservoirWhite = (boardSize*boardSize - 1)/2 + 1;
calcCapturedBlack = 0;
calcCapturedWhite = 0;
if(!state.metricsReady) {
metrics.calc(boardSize);
+ calcCaptured(metrics, state.capturedBlack, state.capturedWhite);
state.metricsReady = true;
}
@@ -104,17 +106,19 @@ bool GobanModel::isPointOnBoard(const Position& p) {
void GobanModel::calcCaptured(Metrics& m, int capturedBlack, int capturedWhite) {
using namespace glm;
- if (capturedBlack != calcCapturedBlack || capturedWhite != calcCapturedWhite) {
+ capturedBlack = capturedWhite = m.maxc;
+ //if (capturedBlack != calcCapturedBlack || capturedWhite != calcCapturedWhite) {
- float cc0x = m.bowlsCenters[0];
- float cc0z = m.bowlsCenters[2];
- float cc1x = m.bowlsCenters[3];
- float cc1z = m.bowlsCenters[5];
- float ddcy = 0.5f*m.h - m.innerBowlRadius - 0.3f;
+ float cc0x = 0.0f;//m.bowlsCenters[0];
+ float cc0z = 0.0f;//m.bowlsCenters[2];
+ float cc1x = 0.0f;//m.bowlsCenters[3];
+ float cc1z = 0.0f;//m.bowlsCenters[5];
+ float magic = 0.0f;
+ float ddcy = 0.5f*m.h - m.innerBowlRadius - magic;
- vec3 s0a(cc0x, -0.3, cc0z);
+ vec3 s0a(cc0x, -magic, cc0z);
vec3 s1a(cc0x, ddcy, cc0z);
- vec3 s0b(cc1x, -0.3, cc1z);
+ vec3 s0b(cc1x, -magic, cc1z);
vec3 s1b(cc1x, ddcy, cc1z);
vec3 sy(0.0f, m.stoneSphereRadius - 0.5*m.h, 0.0f);
@@ -122,16 +126,17 @@ void GobanModel::calcCaptured(Metrics& m, int capturedBlack, int capturedWhite)
for (int i = 0; i < 2 * maxCaptured; ++i) {
float ccx = cc0x;
float ccz = cc0z;
- float rr = m.innerBowlRadius;
- float ccy = 0.1f - rr;
+ float rr = 0.99f * m.innerBowlRadius;
+ float ccy = 0.0f;//0.1f - rr;
vec3 s1 = s1a;
vec3 s0 = s0a;
int di = calcCapturedBlack;
bool white = false;
- if (i + calcCapturedWhite >= maxCaptured + capturedWhite || (i + calcCapturedBlack >= capturedBlack && i = maxCaptured + capturedWhite
+ || (i + calcCapturedBlack >= capturedBlack && i = capturedBlack) {
ccx = cc1x;
ccz = cc1z;
@@ -157,10 +162,10 @@ void GobanModel::calcCaptured(Metrics& m, int capturedBlack, int capturedWhite)
dz = dir.z;
}
for (int j = white ? maxCaptured:0; j < i + di; ++j) {
- float ax = (dx + ccx - ddc[3 * j + 0]);
- float az = (dz + ccz - ddc[3 * j + 2]);
+ float ax = (dx + ccx - ddc[4 * j + 0]);
+ float az = (dz + ccz - ddc[4 * j + 2]);
if (az*az + ax * ax < 4.0f*m.stoneSphereRadius*m.stoneSphereRadius) {
- dy = max(dy, ddc[3 * j + 1] + sqrt(4.0f*m.stoneSphereRadius*m.stoneSphereRadius - az*az - ax*ax) - 2.0f*m.stoneSphereRadius + m.h - ccy);//ddc[3 * j + 1] + h - ccy);
+ dy = max(dy, ddc[4 * j + 1] + sqrt(4.0f*m.stoneSphereRadius*m.stoneSphereRadius - az*az - ax*ax) - 2.0f*m.stoneSphereRadius + m.h - ccy);
}
}
if (dy < mindy) {
@@ -169,23 +174,25 @@ void GobanModel::calcCaptured(Metrics& m, int capturedBlack, int capturedWhite)
mindz = dz;
}
}
- ddc[3 * (i+di) + 0] = ccx + mindx;
- ddc[3 * (i+di) + 1] = ccy + mindy;
- ddc[3 * (i+di) + 2] = ccz + mindz;
+ ddc[4 * (i+di) + 0] = ccx + mindx;
+ ddc[4 * (i+di) + 1] = ccy + mindy;
+ ddc[4 * (i+di) + 2] = ccz + mindz;
+ ddc[4 * (i+di) + 3] = board.getRandomStoneRotation();
}
calcCapturedBlack = capturedBlack;
calcCapturedWhite = capturedWhite;
- }
+ //}
int dBlack = max(capturedBlack - m.maxc, 0);
int dWhite = max(capturedWhite - m.maxc, 0);
for (int i = 0; i < m.maxc; ++i){
- m.tmpc[3 * i + 0] = ddc[3 * (i + dBlack) + 0];
- m.tmpc[3 * i + 1] = ddc[3 * (i + dBlack) + 1];
- m.tmpc[3 * i + 2] = ddc[3 * (i + dBlack) + 2];
- m.tmpc[3 * m.maxc + 3 * i + 0] = ddc[3 * maxCaptured + 3 * (i + dWhite) + 0];
- m.tmpc[3 * m.maxc + 3 * i + 1] = ddc[3 * maxCaptured + 3 * (i + dWhite) + 1];
- m.tmpc[3 * m.maxc + 3 * i + 2] = ddc[3 * maxCaptured + 3 * (i + dWhite) + 2];
-
+ m.tmpc[4 * i + 0] = ddc[4 * (i + dBlack) + 0];
+ m.tmpc[4 * i + 1] = ddc[4 * (i + dBlack) + 1];
+ m.tmpc[4 * i + 2] = ddc[4 * (i + dBlack) + 2];
+ m.tmpc[4 * i + 3] = ddc[4 * (i + dBlack) + 3];
+ m.tmpc[4 * m.maxc + 4 * i + 0] = ddc[4 * maxCaptured + 4 * (i + dWhite) + 0];
+ m.tmpc[4 * m.maxc + 4 * i + 1] = ddc[4 * maxCaptured + 4 * (i + dWhite) + 1];
+ m.tmpc[4 * m.maxc + 4 * i + 2] = ddc[4 * maxCaptured + 4 * (i + dWhite) + 2];
+ m.tmpc[4 * m.maxc + 4 * i + 3] = ddc[4 * maxCaptured + 4 * (i + dWhite) + 3];
}
}
@@ -218,6 +225,12 @@ void GobanModel::onGameMove(const Move& move) {
else {
prevPass = false;
state.msg = GameState::NONE;
+ if(state.holdsStone == false) {
+ if (state.colorToMove == Color::BLACK)
+ state.reservoirBlack -= 1;
+ else
+ state.reservoirWhite -= 1;
+ }
}
state.holdsStone = false;
changeTurn();
@@ -232,7 +245,6 @@ void GobanModel::onBoardChange(const Board& result) {
state.capturedBlack = board.capturedCount(Color::BLACK);
state.capturedWhite = board.capturedCount(Color::WHITE);
- calcCaptured(metrics, state.capturedBlack, state.capturedWhite);
spdlog::debug("over {} ready {}", over, result.territoryReady);
diff --git a/src/GobanModel.h b/src/GobanModel.h
index f30e74b..a799968 100644
--- a/src/GobanModel.h
+++ b/src/GobanModel.h
@@ -18,7 +18,8 @@ class ElementGame;
class GobanModel: public GameObserver {
public:
GobanModel(ElementGame *p, int boardSize = Board::DEFAULTSIZE, int handicap = 0, float komi = 0.0f)
- : parent(p), prevPass(false), over(false), invalidated(false), cursor({0,0}) {
+ : parent(p), prevPass(false), over(false), invalidated(false),
+ calcCapturedBlack(0), calcCapturedWhite(0), cursor({0,0}) {
spdlog::info("Preloading sounds...");
//newGame(boardSize, handicap, komi);
}
@@ -80,7 +81,7 @@ class GobanModel: public GameObserver {
static const int maxCaptured = 191;
int calcCapturedBlack, calcCapturedWhite;
- float ddc[6 * maxCaptured];
+ float ddc[8 * maxCaptured];
Metrics metrics;
diff --git a/src/GobanShader.cpp b/src/GobanShader.cpp
index 4af52fc..5f7fef5 100644
--- a/src/GobanShader.cpp
+++ b/src/GobanShader.cpp
@@ -129,6 +129,8 @@ void GobanShader::initProgram(const std::string& vertexProgram, const std::strin
iContrast = glGetUniformLocation(gobanProgram, "contrast");
iBlackCapturedCount = glGetUniformLocation(gobanProgram, "iBlackCapturedCount");
iWhiteCapturedCount = glGetUniformLocation(gobanProgram, "iWhiteCapturedCount");
+ iBlackReservoirCount = glGetUniformLocation(gobanProgram, "iBlackReservoirCount");
+ iWhiteReservoirCount = glGetUniformLocation(gobanProgram, "iWhiteReservoirCount");
iModelView = glGetUniformLocation(gobanProgram, "glModelViewMatrix");
iAnimT = glGetUniformLocation(gobanProgram, "iAnimT");
@@ -239,7 +241,7 @@ void GobanShader::setMetrics(const Metrics &m) {
glUniform1f(iContrast, contrast);
glUniform1f(fsu_bowlRadius, br);
glUniform1f(fsu_bowlRadius2, br2);
- glUniform3fv(fsu_cc, 2, m.bowlsCenters);
+ glUniform3fv(fsu_cc, 4, m.bowlsCenters);
}
void GobanShader::destroy(void) {
@@ -288,7 +290,10 @@ void GobanShader::draw(const GobanModel& model, const DDG::Camera& cam, int upda
spdlog::debug("place stones via glBufferData()");
glUniform1i(iBlackCapturedCount, view.state.capturedBlack);
glUniform1i(iWhiteCapturedCount, view.state.capturedWhite);
- glUniform3fv(iddc, 2 * Metrics::maxc, model.metrics.tmpc);
+ glUniform1i(iBlackReservoirCount, static_cast(view.state.reservoirBlack / 2));
+ glUniform1i(iWhiteReservoirCount, static_cast(view.state.reservoirWhite / 2));
+ glUniform4fv(iddc, 2 * Metrics::maxc, model.metrics.tmpc);
+
glBindBuffer(GL_UNIFORM_BUFFER, bufStones);
glBufferData(GL_UNIFORM_BUFFER, view.board.getSizeOf(), view.board.getStones(), GL_DYNAMIC_DRAW);
glBindBuffer(GL_UNIFORM_BUFFER, 0);
diff --git a/src/GobanShader.h b/src/GobanShader.h
index 00b4099..c4e9840 100644
--- a/src/GobanShader.h
+++ b/src/GobanShader.h
@@ -101,6 +101,8 @@ class GobanShader {
GLint iWhiteCapturedCount;
GLint iBlackCapturedCount;
+ GLint iWhiteReservoirCount;
+ GLint iBlackReservoirCount;
GLint iddc;
diff --git a/src/GobanView.cpp b/src/GobanView.cpp
index f0d19d7..efef157 100644
--- a/src/GobanView.cpp
+++ b/src/GobanView.cpp
@@ -356,7 +356,7 @@ int GobanView::updateCursor(const Position& lastCursor){
auto& np = model.board[cursor];
if(state.holdsStone != model.state.holdsStone) {
- board.setRandomStoneRotation();
+ board.setRandomStoneRotation();
state.holdsStone = model.state.holdsStone;
}
if(model.state.holdsStone && model.isPointOnBoard(cursor) && np.stone == Color::EMPTY){
@@ -375,7 +375,7 @@ void GobanView::onGameMove(const Move& move) {
board.removeOverlay(lastMove);
}
lastMove = move.pos;
- board.setRandomStoneRotation();
+ board.setRandomStoneRotation();
board.setOverlay(move.pos, ss.str(), move.col);
}
}
diff --git a/src/Metrics.cpp b/src/Metrics.cpp
index 768fa8b..788bcb6 100644
--- a/src/Metrics.cpp
+++ b/src/Metrics.cpp
@@ -12,17 +12,27 @@ void Metrics::calc(unsigned NDIM) {
y = b / 2.0f + d;
px = sqrtf(stoneSphereRadius*stoneSphereRadius - y*y);
float r1 = 0.5f*sqrtf(4.0f*px*px + b*(2.0f*b-h+2.0f*stoneSphereRadius));
- float br = sqrtf(0.08f/fNDIM*19.0f);
- br2 = br + sqrtf(0.15f) - sqrtf(0.08f);
+ float br = sqrtf(0.12f * 9.0f/ fNDIM );
+ br2 = br + sqrtf(0.15f) - sqrtf(0.12f);
dbr = - sqrtf(0.15f) + br2;
stoneRadius = r1;
innerBowlRadius = br;
bowlsCenters[0] = -1.5f - dbr;
- bowlsCenters[1] = -0.1f;
- bowlsCenters[2] = 0.55f - dbr;
+ bowlsCenters[1] = -0.35f;
+ bowlsCenters[2] = 1.0f - br2;
+
bowlsCenters[3] = 1.5f + dbr;
- bowlsCenters[4] = -0.1f;
- bowlsCenters[5] = -0.55f + dbr;
+ bowlsCenters[4] = -0.35f;
+ bowlsCenters[5] = -1.0f + br2;
+
+ bowlsCenters[6] = -1.5f - dbr;
+ bowlsCenters[7] = 0.35f;
+ bowlsCenters[8] = 1.0f - 3.2*br2;
+
+ bowlsCenters[9] = 1.5f + dbr;
+ bowlsCenters[10] = 0.35f;
+ bowlsCenters[11] = -1.0f + 3.2*br2;
+
squareSize = ww;
stoneHeight = 0.5f*h;
}
diff --git a/src/Metrics.h b/src/Metrics.h
index 2580097..cfc9008 100644
--- a/src/Metrics.h
+++ b/src/Metrics.h
@@ -16,12 +16,12 @@ class Metrics {
float stoneSphereRadius;
float stoneRadius;
float innerBowlRadius;
- float bowlsCenters[6];
+ float bowlsCenters[12];
float squareSize;
float stoneHeight;
- static const int maxc = 32;
- float tmpc[6 * maxc];
+ static const int maxc = 91;
+ float tmpc[8 * maxc];
float resolution[2];
float translate[3];
diff --git a/src/player.h b/src/player.h
index 978e9f6..abb3618 100644
--- a/src/player.h
+++ b/src/player.h
@@ -15,7 +15,7 @@
class Player
{
public:
- enum Role { NONE = 0, WHITE = 1, BLACK = 2, COACH = 4, SPECTATOR = 8, STANDBY = 16};
+ enum Role { NONE = 0, WHITE = 1, BLACK = 2, COACH = 4, SPECTATOR = 8, KIBITZ = 16, STANDBY = 32};
enum Type { LOCAL = 1, HUMAN = 2, ENGINE = 4 };
Player(const std::string& name, int role, int type) : name(name), role(role), type(type) {