PageRenderTime 33ms CodeModel.GetById 25ms app.highlight 4ms RepoModel.GetById 1ms app.codeStats 0ms

/baduk-lua.tex

http://tex-baduk.googlecode.com/
LaTeX | 570 lines | 373 code | 135 blank | 62 comment | 0 complexity | a252292a2c798479898157dc15a3e982 MD5 | raw file
  1
  2\writestatus{loading}{Go/WeiQi/Baduk Lua module}
  3
  4
  5\startluacode
  6
  7Game = [[
  8(;CA[Windows-1252]SZ[19]AP[MultiGo:4.4.4]EV[14th ch-kr Tengen, game 1]DT[2010-07-11]
  9PB[Chen Yaoye]BR[9p]PW[Park Junghwan]WR[8p]KM[6.5]RE[B+R]
 10;B[pd];W[dd];B[qp];W[dq];B[co];W[oq];B[mp];W[qf];B[pi];W[md];B[qe];W[pf];B[oe];W[pe]
 11;B[qd];W[od];B[of];W[og];B[nd];W[oc];B[nc];W[pc];B[rf];W[rg];B[ng];W[qc];B[rc];W[sf]
 12;B[rd];W[rb];B[ob];W[qb];B[pg];W[re];B[oh];W[oo];B[qn];W[pn];B[pm];W[om];B[pl];W[kp]
 13;B[mn];W[pp];B[ep];W[qq];B[qo];W[eq];B[fp];W[gq];B[gp];W[hq];B[hp];W[rq];B[iq];W[ir]
 14;B[jr];W[ip];B[jq];W[cq];B[nr];W[or];B[cf];W[di];B[ef];W[fc];B[dk];W[fi];B[gf];W[ek]
 15;B[el];W[dl];B[cl];W[dm];B[ck];W[fk];B[em];W[id];B[eh];W[ei];B[cc];W[cd];B[bd];W[dc]
 16;B[bb];W[cb];B[bc];W[mc];B[mb];W[ne];B[nb];W[kc];B[me];W[en];B[dn];W[ri];B[hk];W[hi]
 17;B[jd];W[ic];B[gd];W[gc];B[jk];W[fl];B[cm];W[ji];B[kd];W[le];B[jc];W[jf];B[mf];W[jb]
 18;B[kb];W[ib];B[np];W[ol];B[po];W[op];B[on];W[nn];B[no];W[pn];B[qg];W[rf];B[on];W[ce]
 19;B[be];W[pn];B[gh];W[fh];B[fg];W[hh];B[on];W[cg];B[bf];W[pn];B[bp];W[is];B[on];W[jp]
 20;B[lq];W[pn];B[br];W[cr];B[on];W[il];B[nm];W[jl];B[kl];W[kk];B[km];W[lk];B[hl];W[hm]
 21;B[jj];W[dg];B[df];W[kj];B[gm];W[kn];B[hn];W[jm];B[lm];W[ik];B[jn])
 22]]
 23
 24
 25EMPTY = 0
 26BLACK = 1
 27WHITE = 2
 28ONSTACK = 4
 29DEAD = 5
 30
 31Status = {FirstMove = 1, LastMove = 999, FirstMoveLabel = 1, LastMoveLabel = 999} 
 32
 33function displayMove (num)
 34	if num < Status.FirstMove or num > Status.LastMove then return false else return true end
 35end 
 36
 37
 38function writeLabel (num)
 39	if num < Status.FirstMoveLabel or num > Status.LastMoveLabel then return false else return true end
 40end
 41
 42
 43function setLabelBoundaries (start, stop)
 44	Status.FirstMoveLabel = start
 45	Status.LastMoveLabel = stop
 46end
 47
 48
 49function setMoveBoundaries (start, stop)
 50	Status.FirstMove = start
 51	Status.LastMove = stop
 52end
 53
 54Board = { Size = 19, LastColor = WHITE, MoveNumber = 0, Label = {}; {}}
 55
 56Big = { Board = 15, Grid = 0.7, Stone = 14.5, Label = 0.9 }		--> Big sized goban 
 57Medium = { Board = 12, Grid = 0.5, Stone = 11.5, Label = 0.7 }	--> Medium sized goban
 58Small = { Board = 10, Grid = 0.4, Stone = 9.5, Label = 0.55 }	 	--> Small sized goban
 59
 60Unit = Big
 61
 62Hoshi19 = {{x=4, y=4}, {x=4, y=10}, {x=4, y=16}, {x=10, y=4}, {x=10, y=10}, {x=10, y=16}, {x=16, y=4}, {x=16, y=10},{x=16, y=16}}
 63Hoshi13 = {{x=4, y=4}, {x=4, y=10}, {x=10, y=4}, {x=10, y=10}, {x=7, y=7}}
 64Hoshi9 = {{x=3, y=3}, {x=3, y=7}, {x=7, y=3}, {x=7, y=7}, {x=5, y=5}}
 65
 66Hoshi = Hoshi19
 67
 68---------------------------------------------------------
 69--- TeX (MetaPost) drawing functions
 70---------------------------------------------------------
 71
 72function stone (x, y, c)	--> x, y: number; c: string (color: white or black)
 73	tex.sprint("fill fullcircle scaled " .. Unit.Stone .. " shifted (" .. x*Unit.Board .. "," .. y*-Unit.Board .. ") withcolor " .. c .. " ;")
 74	tex.sprint("draw fullcircle scaled " .. Unit.Stone .. " shifted (" .. x*Unit.Board .. "," .. y*-Unit.Board .. ") withcolor black ;")
 75end
 76
 77
 78function circleMarker (x, y, c)
 79	tex.sprint("draw fullcircle scaled " .. 0.6*Unit.Stone .. " shifted (" .. x*Unit.Board .. "," .. y*-Unit.Board .. ") withpen pencircle scaled (" .. 2*Unit.Grid .. ") withcolor " .. c .. " ;")
 80end
 81
 82
 83function label (l, x, y, c)
 84	tex.sprint("label(textext(\"\\color[" .. c .. "]{\\bf\\ssxx " .. l .. "}\"),(" .. x*Unit.Board .. ',' .. y*-Unit.Board .. '))  ;')
 85end
 86
 87
 88function drawGoban ()
 89	for i=1, Board.Size do
 90		tex.sprint("draw (" .. Unit.Board .. "," .. i*-Unit.Board .. ") -- (" .. Board.Size*Unit.Board .. "," .. i*-Unit.Board .. ") withpen pencircle scaled " .. Unit.Grid .. " ;")
 91		tex.sprint("draw (" .. i*Unit.Board .. "," .. -Unit.Board .. ") -- (" .. i*Unit.Board .. "," .. Board.Size*-Unit.Board .. ") withpen pencircle scaled " .. Unit.Grid .. " ;")
 92	end
 93
 94	tex.sprint("draw (" .. Unit.Board .. "," .. -Unit.Board .. ") -- (" .. Board.Size*Unit.Board .. "," .. -Unit.Board ..") -- (" .. Board.Size*Unit.Board .. "," .. Board.Size*-Unit.Board .. ") -- (" .. Unit.Board .. "," .. Board.Size*-Unit.Board .. ") -- cycle withpen pencircle scaled (" ..2.5*Unit.Grid .. ") ;")
 95
 96	for i=1, #Hoshi do
 97		x = Hoshi[i].x; y = Hoshi[i].y
 98		tex.sprint("drawdot (" .. x*Unit.Board .. "," .. y*-Unit.Board .. ") withpen pencircle scaled (" .. 5*Unit.Grid .. ") ;")
 99	end
100end
101
102
103function drawStones ()
104	for i=1, Board.Size do
105		for j=1, Board.Size do
106			if Board[i][j] == BLACK then stone(i, j, "black") elseif Board[i][j] == WHITE then stone(i, j, "white") end
107			if Board.Label[i][j] > 0 then
108				if Board[i][j] == BLACK then
109					label(Board.Label[i][j], i, j, "white")
110				elseif Board[i][j] == WHITE then
111					label(Board.Label[i][j], i, j, "black")
112				end
113			elseif Board.Label[i][j] < 0 then
114				if Board[i][j] == BLACK then circleMarker(i, j, "white") else circleMarker(i, j, "black") end
115			end
116		end
117	end
118end
119
120
121function displayBoard (name, size, p1, p2)
122
123	if size == "small" then
124		Unit = Small
125	elseif size == "medium" then
126		Unit = Medium
127	else
128		Unit = Big
129	end
130
131	tex.sprint("\\startuseMPgraphic{" .. name .. "}{}")
132	tex.sprint("path p ;")
133
134	drawGoban()
135	drawStones()
136
137	if p1 then
138		local x1, y1 = Point(p1)
139		local x2, y2 = Point(p2)
140		tex.sprint("p:= (" .. (x1-1)*Unit.Board .. "," .. (y1-1)*-Unit.Board ..") -- (" .. x2*Unit.Board .. "," .. (y1-1)*-Unit.Board .. ") -- (" .. x2*Unit.Board .. "," .. y2*-Unit.Board .. ") -- (" .. (x1-1)*Unit.Board .. "," .. y2*-Unit.Board .. ") -- cycle ;")
141		tex.sprint("clip currentpicture to p shifted (" .. Unit.Board/2 .. "," .. -Unit.Board/2 .. ") ;")
142	end
143
144	tex.sprint("\\stopuseMPgraphic")
145	tex.sprint("\\useMPgraphic{" .. name .. "}")
146end
147
148
149function setStone (p, c)		--> c = "black", "white" or "empty" (AB, AW, AE)
150	local x, y = Point(p)
151	if c == "black" then
152		Board[x][y] = BLACK 
153	elseif c == "white" then
154		Board[x][y] = WHITE
155	elseif c == "empty" then
156		Board[x][y] = EMPTY
157	end
158end
159
160
161function Point (p)
162	local x, y = 0, 0
163	local l = "abcdefghijklmnopqrstuvwxyz"
164	x = string.find(l, string.sub(p, 1, 1))
165	y = string.find(l, string.sub(p, 2, 2))
166	return x, y
167end
168
169
170function setMarker (p)
171	local x, y = Point(p)
172	if Board[x][y] > 0 then Board.Label[x][y] = -1 end
173end
174
175
176function playMove (p, c)		--> if p not defined -> pass
177	Board.MoveNumber = Board.MoveNumber + 1	
178	if displayMove(Board.MoveNumber) then
179		if c then
180			if c == "white" then Board.LastColor = WHITE else Board.LastColor = BLACK end
181		else
182			if Board.LastColor == BLACK then Board.LastColor = WHITE else Board.LastColor = BLACK end
183		end
184		if p then
185			local x, y = Point(p)
186			Board[x][y] = Board.LastColor
187			if writeLabel(Board.MoveNumber) then 
188				Board.Label[x][y] = Board.MoveNumber
189			else
190				testDeadStones(x, y)	--> only test dead stones if you dont write label
191			end
192-- here should be test for suicide move, allowed on some rules version 
193		end	
194	end
195end
196
197
198function setBoardSize (s)
199	if s == "small" then
200		Board.Size = 9
201		Hoshi = Hoshi9
202	elseif s == "medium" then
203		Board.Size = 13
204		Hoshi=Hoshi13
205	else
206		Board.Size = 19
207		Hoshi = Hoshi19
208	end
209	setLabelBoundaries(1, 999)
210end
211
212
213function resetBoard ()
214	Board.LastColor = WHITE
215	Board.MoveNumber = 0
216	for i=1, Board.Size do
217		Board[i] = {}
218		Board.Label[i] = {}
219		for j=1, Board.Size do
220			Board[i][j] = EMPTY 
221			Board.Label[i][j] = EMPTY
222		end
223	end
224end
225
226
227---------------------------------------------------------
228--- Deadstone calculator
229---------------------------------------------------------
230
231--- Stack implementation for deadstone calculator
232
233function resetStack ()
234	stack = {}
235end
236
237
238function push (x, y)
239	stack = {next = stack, x = x, y = y}
240end
241
242
243function pop ()
244	if stack then
245		local x, y = stack.x, stack.y
246		stack = stack.next
247		return x, y
248	end
249end
250
251
252--- Deadstone calculator
253
254--- Are x, y valid coordinates? 
255
256function isValid (x, y)
257	if x >= 1 and x <= Board.Size and y >= 1 and y <= Board.Size then return true end
258	return false
259end
260
261--- Reset shadow Goban
262
263shadowboard = {}
264
265function resetShadowBoard (size)
266	for i = 1, size do
267		shadowboard[i] = {}
268	end
269end
270
271--- Na základě stínového gobanu odstraní kameny označené jako mrtvé ze skutečného gobanu.
272
273function removeDeadStones ()
274	for i, k in pairs(shadowboard) do
275		for j, v in pairs(k) do Board[i][j] = EMPTY end
276	end
277end
278
279--- Test, je-li x, y prázdná.
280-- V opačném případě je-li na x, y soupeřův kámen, uloží do zásobníku jeho pozici.
281
282function isEmpty (x, y)
283	if Board[x][y] == EMPTY then
284		return true
285	elseif Board[x][y] ~= myColor and shadowboard[x][y] ~= DEAD then
286		push(x, y)
287	end
288	return false
289end
290
291--- Testuje, zda má kámen na pozici x, y svobodu.
292-- V případě že ne, vrací true, jinak false.
293
294function isDead (x, y)
295	if isValid(x, y+1) and isEmpty(x, y+1) then return false end
296	if isValid(x-1, y) and isEmpty(x-1, y) then return false end
297	if isValid(x, y-1) and isEmpty(x, y-1) then return false end
298	if isValid(x+1, y) and isEmpty(x+1, y) then return false end
299	return true
300end
301
302--- Test for dead group.
303-- If the group with stone on (x, y) is dead, it removes it from goban. 
304-- Can be used to test for suicide.
305
306function deadStones (x, y)
307	resetStack()
308	resetShadowBoard(Board.Size)
309	while isDead(x, y) do
310		shadowboard [x][y] = DEAD
311		x, y = pop()
312		if not x then
313			removeDeadStones()
314			break
315		end
316	end
317end
318
319--- Main entry point for deadstone calculator.
320-- For each neighbour stone it starts test for dead group.
321
322function testDeadStones (x, y)
323	myColor = Board[x][y]
324	if isValid(x+1, y) and Board[x+1][y] ~= EMPTY and Board[x+1][y] ~= myColor then deadStones(x+1, y) end
325	if isValid(x, y+1) and Board[x][y+1] ~= EMPTY and Board[x][y+1] ~= myColor then deadStones(x, y+1) end
326	if isValid(x-1, y) and Board[x-1][y] ~= EMPTY and Board[x-1][y] ~= myColor then deadStones(x-1, y) end
327	if isValid(x, y-1) and Board[x][y-1] ~= EMPTY and Board[x][y-1] ~= myColor then deadStones(x, y-1) end
328end
329
330
331---------------------------------------------------------
332--- SGF parser
333---------------------------------------------------------
334
335--- Very ugly looking first implementation of SGF parser mainly for testing deadstone calculator
336
337
338function blackmove (a, b, c)
339	playMove(c, "black")
340	return b
341end
342
343
344function whitemove (a, b, c)
345	playMove(c, "white")
346	return b
347end
348
349
350function blackstone (a, b, c)
351	print("\\stone[black]{"..c.."}")
352	return b
353end
354
355
356function whitestone (a, b, c)
357	print("\\stone[white]{"..c.."}")
358	return b
359end
360
361
362function emptystone (a, b, c)
363	print("\\stone[empty]{"..c.."}")
364	return b
365end
366
367
368function parseSGF(SGFstring)
369	emptychar = (lpeg.S(" \t\r\n"))^1
370	letter = lpeg.R("az", "AZ")
371	number = (lpeg.R("09"))^1
372	text = (letter + number + lpeg.S(" .,:;+-=_?!@#$%^&*()/"))^1
373
374	axis = letter * letter
375	shortparam = axis + ""
376	longparam = axis * ( ":" * axis )^-1
377
378	FF = lpeg.P("FF[4]") * emptychar^0
379	GM = lpeg.P("GM[1]") * emptychar^0
380	SZ = lpeg.P("SZ[") * number * lpeg.P("]") * emptychar^0
381	DT = lpeg.P("DT[") * text * lpeg.P("]") * emptychar^0
382	EV = lpeg.P("EV[") * text * lpeg.P("]") * emptychar^0
383	PB = lpeg.P("PB[") * text * lpeg.P("]") * emptychar^0
384	PW = lpeg.P("PW[") * text * lpeg.P("]") * emptychar^0
385	BR = lpeg.P("BR[") * text * lpeg.P("]") * emptychar^0
386	WR = lpeg.P("WR[") * text * lpeg.P("]") * emptychar^0
387	KM = lpeg.P("KM[") * text * lpeg.P("]") * emptychar^0
388	RE = lpeg.P("RE[") * text * lpeg.P("]") * emptychar^0
389	CA = lpeg.P("CA[") * text * lpeg.P("]") * emptychar^0
390	AP = lpeg.P("AP[") * text * lpeg.P("]") * emptychar^0
391	DT = lpeg.P("DT[") * text * lpeg.P("]") * emptychar^0
392
393
394
395	B = lpeg.P("B[") * lpeg.Cmt(shortparam, blackmove) * lpeg.P("]")	* emptychar^0
396	W = lpeg.P("W[") * lpeg.Cmt(shortparam, whitemove) * lpeg.P("]") * emptychar^0
397
398	rootproperty = FF + GM + SZ + DT + EV + PB + PW + BR + WR + KM + RE + CA + AP + DT
399	property = B + W
400
401	rootnode = lpeg.P(";") * (rootproperty)^1
402	node = lpeg.P(";") * property
403
404	sequence = rootnode^0 * node^1
405
406	gameTree = lpeg.P("(") * sequence^1 * lpeg.P(")")
407
408--	tex.sprint("SGFparse: " .. SGFstring)
409--	tex.sprint("::")
410--	tex.sprint()
411
412	resetBoard ()
413	if not lpeg.match(gameTree, SGFstring) then
414		tex.sprint("Invalid SGF file")
415	end
416
417end
418
419
420\stopluacode
421
422\def\move#1%
423	{\ctxlua{playMove("#1")}}
424
425%\def\move
426%	{\dosingleargument\domove}
427
428%\def\domove[#1]{#2}
429%	{\iffirstargument
430%		\ctxlua{playMove("#2", "#1")}
431%	\else
432%		\ctxlua{playMove("#2")}
433%	\fi}
434
435\def\pass
436	{\ctxlua{playMove()}}
437
438\def\stone[#1]#2%
439	{\ctxlua{setStone("#2", "#1")}}
440
441\def\marker#1%
442	{\ctxlua{setMarker("#1")}}
443
444\def\newboard
445	{\dosingleargument\donewboard}
446
447\def\donewboard[#1]%
448	{\iffirstargument
449		\ctxlua{setBoardSize("#1")}
450	\else
451		\ctxlua{setBoardSize("big")}
452	\fi}
453
454\def\resetnumbering
455	{\ctxlua{resetBoard()}}
456
457\def\drawboard
458	{\dosingleargument\dodrawboard}
459
460\def\dodrawboard[#1]%
461	{\iffirstargument
462		\ctxlua{displayBoard(0, "#1")}
463	\else
464		\ctxlua{displayBoard(0, "medium")}
465	\fi}
466
467\def\drawpartialboard#1#2%
468	{\ctxlua{displayBoard(0, "medium", "#1", "#2")}}
469
470\def\parse#1%
471	{\ctxlua{parseSGF("#1")}}
472
473\def\position
474	{\dosingleargument\doposition}
475
476\def\doposition[#1]%
477	{\iffirstargument
478		\ctxlua{setMoveBoundaries(1, #1); parseSGF(Game)}
479	\else
480		{\ctxlua{parseSGF(Game)}}
481	\fi}
482
483\def\labels#1#2%
484	{\ctxlua{setLabelBoundaries(#1, #2)}}
485
486
487\starttext
488
489
490\newboard
491
492\position[40]
493\drawboard
494
495\labels{41}{999}
496\position[100]
497\drawboard[small]
498
499\labels{101}{999}
500\position[999]
501\drawboard[big]
502
503\labels{999}{999}
504\position{999}
505\drawboard
506
507The annual bilateral Tengen championship is back. This year, Park Junghwan Chunwon (Korean for Tengen) meet Chen Yaoye Tianyuan (Chinese for Tengen). This tournament is sponsored by Sports Korea newspaper and Xinmin Wanbo evening paper.
508
509Chen Yaoye of China opened the first game by an early 165 moves resignation game. Chen who played black in the first game ended the game by cutting Park's group. The cut will lead to a favorable ko fight for black. I'm not sure whether white group can survive here or not, but perhaps Park didn't think he'll win the fight, so he resigned.
510
511% \newboard
512% \parse{;B[pd];W[dd];B[pq];W[dp];B[fq];W[cn];B[qk];W[jp];B[dr];W[gq];B[fp];W[fr];B[er];W[gr]
513% ;B[cp];W[cq];B[bq];W[bp];B[co];W[bo];B[do];W[br];B[dq];W[cr];B[dn];W[mq];B[cm];W[bn]
514% ;B[po];W[dm];B[nc];W[fc];B[be];W[ce];B[bd];W[bf];B[cf];W[cg];B[df];W[bg];B[dg];W[dh]
515% ;B[eh];W[di];B[dc];W[cc];B[cb];W[cd];B[bc];W[db];B[ec];W[ed];B[eb];W[eg];B[ef];W[fe]
516% ;B[gd];W[fd];B[da];W[fg]}
517% \drawboard
518% \clearnumbers
519% \parse{;B[em];W[dl];B[qe];W[fm];B[fn];W[el];B[gm];W[en]}
520% \drawboard
521% \clearnumbers
522% \parse{;B[eo];W[ok]
523% ;B[oj];W[nj];B[pj];W[nk];B[ni];W[mi];B[mh];W[li];B[pm];W[qc];B[em]}
524% \drawboard
525% \clearnumbers
526% \parse{;W[re];B[rd];W[qd]
527% ;B[rc];W[nh];B[oi];W[pe];B[qf];W[pc];B[od];W[rf];B[rb];W[qg];B[pf];W[of];B[pg];W[ph]
528% ;B[og];W[oh];B[oe]}
529% \drawboard
530% \clearnumbers
531% \parse{;W[qi];B[ng];W[rk];B[rl];W[rj];B[ql];W[rh];B[fl];W[jd]}
532% \drawboard
533% \clearnumbers
534% \parse{;B[lh];W[kh]
535% ;B[lf];W[ki];B[jf];W[he];B[kc];W[kd];B[jc];W[ic];B[ib];W[le];B[kg];W[lc];B[lb];W[kb]
536% ;B[jb];W[mb];B[ka];W[mc];B[ob];W[ig]}
537% \drawboard
538% \clearnumbers
539% \parse{;B[ej];W[dj];B[fk];W[ek];B[lr];W[mr];B[iq];W[ip]
540% ;B[hp];W[jq];B[hq];W[jr];B[mo];W[or];B[pr];W[lp];B[ir];W[jg];B[me];W[fb];B[hb];W[fa]
541% ;B[ba];W[is];B[hs];W[js];B[gp];W[sl];B[sm];W[sk];B[rn];W[ps];B[qs];W[os];B[qr];W[if]
542% ;B[gi];W[md];B[mf];W[hj];B[ei];W[nm];B[jl];W[hl];B[lm];W[kl]}
543% \drawboard
544% \clearnumbers
545% \parse{;B[km];W[jm];B[kk];W[ll]
546% ;B[ml];W[lk];B[mk];W[lj];B[mm];W[mj];B[mp];W[lo];B[nq];W[mn];B[nn];W[ln];B[lq];W[ls]
547% ;B[nr];W[ms];B[jn];W[im];B[cl];W[dk];B[ns];W[no];B[ks];W[on];B[kp];W[ko];B[in];W[hm]
548% ;B[hn];W[kn]}
549% \drawboard
550% \clearnumbers
551% \parse{;B[hi];W[pn];B[qn];W[op];B[oq];W[pp];B[qp];W[ii]}
552% \drawboard
553% \clearnumbers
554% \parse{;B[ih];W[gj];B[fj];W[ji]
555% ;B[sd];W[se];B[hg];W[ff];B[jo];W[kq];B[io];W[nl]}
556% \drawboard
557% \clearnumbers
558% \parse{;B[hd];W[id];B[gb];W[na];B[la];W[oa]
559% ;B[pa];W[nd];B[nb];W[ma];B[pb];W[fh];B[fi];W[ea];B[db];W[ge];B[ne];W[ld];B[pi];W[qh]
560% ;B[kr];W[kp];B[gk];W[hk];B[ds];W[cs];B[af];W[ag];B[ae];W[ga];B[ha];W[np];B[mq];W[pk]
561% ;B[qj];W[pl];B[om];W[gl];B[hh];W[jh];B[qm];W[nn];B[qo];W[hc];B[gc];W[ie];B[fm])}
562% \drawboard
563% 
564Park Junghwan even the game by winning the second game by 2.5 points. The game was quite territory oriented. Black claimed the right side, while white went for the left side and aimed for the upper board. There was a big trade at move 205. White sacrificed his 7 stones (about 12 points) for black's 5 stones. The trade was even I think. However, black eventually came out ahead after the trade.
565
566
567
568\stoptext
569
570% ;FF[4];AW[gg:hh][ij][kl][op]AB[kk][gh]AB[ll]AW[oo]AE[hg];B[dd]BT[567];W[cc]WT[1234];B[];W[];B[dc];W[cd];B[ce];W[be];B[cf];W[bf];B[cg]