summaryrefslogtreecommitdiff
path: root/obsolete/macros/context/contrib/context-sgf/tex/context/third/sgf/deadstone.lua
blob: 656de4e17c247cda9d8c8c6419121c87b6f1c852 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
if not modules then modules = { } end modules ['deadstone'] = {
    version   = 0.100,
    comment   = "Dead stone calculator for go",
    author    = "Wolfgang Schuster",
    copyright = "Public Domain",
}

--[[ldx--
<p>This is the <l n='lua'/> version of my deadstone calculator.
It is a nearly one to one copy of my original idea of my method,
I developed to find the dead stones on the goban.</p>
--ldx]]--

laststone = 1

--[[ldx--
<p>The <ldx:function>clearboard</ldx:function> is called at the
begin of a new board to initialize all fields with the value 0
and the margins with the value 3. I need this values for the later
calculations of the field states.</p>
--ldx]]--

function clearboard()
  field = {}
  for y=0,tex.count.boardsize+1 do
    field[y] = {}
    for x=0,tex.count.boardsize+1 do
      if x==0 then
        field[y][x] = { 3, 0 }
      elseif x==tex.count.boardsize+1 then
        field[y][x] = { 3, 0 }
      elseif y==0 then
        field[y][x] = { 3, 0 }
      elseif y==tex.count.boardsize+1 then
        field[y][x] = { 3, 0 }
      else
        field[y][x] = { 0, 0 }
      end
    end
  end
end

--[[ldx--
<p>To decide wheter I handle in the calculation a white or a black
stone the state for stone and enemy depends of the current color.</p>
<p>The value for marked depends also on the current stone color to
reset already living stones in the last step back to the normal color.
This could have been done also by checking the current stone color
but two different values work without this test.</p>
<p>The values for wall, error (should never happen) and dead is the
same for both, black and white stones. There is no need to make a
difference between them.</p>
--ldx]]--

function blackstone()
  stone=1
  enemy=2
  wall=3
  marked=4
  error=6
  dead=7
end

function whitestone()
  stone=2
  enemy=1
  wall=3
  marked=5
  error=6
  dead=7
end

--[[ldx--
<p>The <ldx:function>doprocesstones</ldx:function> is used to call all
subfunctions. It is called twice, once for the black stones and a second
time for the white stones.</p>
--ldx]]--

function doprocesstones()
  markstones()
  deadstones()
  -- for n=1,tex.count.deadcount
  --   checkstones()
  -- end
  checkstones()
  checkstones()
  revertstones()
end

--[[ldx--
<p>The order in which the last <ldx:function>doporocesstones</ldx:function>
ist called depends on the current placed stones.</p>
<p>This mean if the last stone was a black one, we look at the begin for
dead white stone and reverse if the last stone was a white one.</p>
<p>We could check the current stone color with the variable
<ldx:variable>laststone</ldx:variable> and test for the numeric value.</p>
--ldx]]--

function processtones()
  -- we placed a black stone
  if laststone==1 then
    processwhitetones()
    processblackstones()
  -- we placed a white stone
  elseif laststone==2 then
    processblackstones()
    processwhitetones()
  end
end

function processblackstones()
  blackstone()
  doprocesstones()
end

function processwhitetones()
  whitestone()
  doprocesstones()
end

--[[ldx--
<p>The <ldx:function>markstones</ldx:function> mark the stones if they
have the right stones on their sides or let them keep untouched.</p>
--ldx]]--

function markstones()
  for y=1,tex.count.boardsize do
    for x=1,tex.count.boardsize do
      if field[y][x][1]==stone then
        if (field[y][x-1][1]==wall or field[y][x-1][1]==enemy or field[y][x-1][1]==marked)
          and (field[y][x+1][1]==wall or field[y][x+1][1]==enemy or field[y][x+1][1]==stone)
          and (field[y-1][x][1]==wall or field[y-1][x][1]==enemy or field[y-1][x][1]==marked)
          and (field[y+1][x][1]==wall or field[y+1][x][1]==enemy or field[y+1][x][1]==stone)
        then
          field[y][x] = { marked, field[y][x][2] }
        end
      end
    end
  end
end

--[[ldx--
<p>The <ldx:function>deadstones</ldx:function> set stones with the value marked
to dead if the conditions in the function are true.</p>
--ldx]]--

function deadstones()
  for y=tex.count.boardsize,1,-1 do
    for x=tex.count.boardsize,1,-1 do
      if field[y][x][1]==marked then
        if (field[y][x-1][1]==wall or field[y][x-1][1]==enemy or field[y][x-1][1]==marked)
          and (field[y][x+1][1]==enemy or field[y][x+1][1]==wall or field[y][x+1][1]==dead)
          and (field[y+1][x][1]==enemy or field[y+1][x][1]==wall or field[y+1][x][1]==dead)
        then
          field[y][x] = { dead, field[y][x][2] }
        end
      end
    end
  end
end

--[[ldx--
<p>Because the <ldx:function>deadstones</ldx:function> can sometimes set
already living stones to dead. To prevent this in the final result this
function looks through all stones with a loop in reverse direction and
reset the values to their original value if the stone is not dead and
should remain on the board. The function is currently called twice within
processtones but this can be changed with the counter deadcount.</p>
--ldx]]--

function checkstones()
  for y=1,tex.count.boardsize do
    for x=1,tex.count.boardsize do
      if field[y][x][1]==marked then
        field[y][x] = { stone, field[y][x][2] }
      elseif field[y][x][1]==dead then
        if (field[y][x-1][1]==dead or field[y][x-1][1]==enemy or field[y][x-1][1]==wall)
          and (field[y][x+1][1]==dead or field[y][x+1][1]==enemy or field[y][x+1][1]==wall)
          and (field[y-1][x][1]==dead or field[y-1][x][1]==enemy or field[y-1][x][1]==wall)
          and (field[y+1][x][1]==dead or field[y+1][x][1]==enemy or field[y+1][x][1]==wall)
        then
          field[y][x] = { dead, field[y][x][2] }
        else
          field[y][x] = { stone, field[y][x][2] }
        end
      end
    end
  end
end

--[[ldx--
<p>The last thing to do after all dead stones are found on the board
is to remove them and to reset all other stones which are still in a
marked state or we will get wrong input for the next move.</p>
--ldx]]--

function revertstones()
  for y=1,tex.count.boardsize do
    for x=1,tex.count.boardsize do
      if field[y][x][1]==marked then
        field[y][x] = { stone, field[y][x][2] }
      elseif field[y][x][1]==dead then
        appendtodeadstonelist(y,x,stone,field[y][x][2]) -- append to deadstonelist
        field[y][x] = { 0, 0 }                          -- before reseting the field
      end
    end
  end
end

--[[ldx--
<p>To use the dead stones we found in this run on the board for later
use they are saved in two commalist, one for white stones and another
one for the black ones. They can be used by other macros, the only thing
here is done is to append the removed stones in the current run to the
already romved stones in one of the former calculations.</p>
--ldx]]--

function appendtodeadstonelist(row,column,color,count)
  if color==1 then
    tex.print("\\expanded{\\appendtocommalist{{" .. row .. ":" .. column .. ":1:" .. count .. "}}}\\deadblackstones")
  elseif color==2 then
    tex.print("\\expanded{\\appendtocommalist{{" .. row .. ":" .. column .. ":2:" .. count .. "}}}\\deadwhitestones")
  end
end