# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# This is GNU Go, a Go program. Contact gnugo@gnu.org, or see #
# http://www.gnu.org/software/gnugo/ for more information. #
# Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, #
# 2008 and 2009 by the Free Software Foundation. #
# This program is free software; you can redistribute it and/or #
# modify it under the terms of the GNU General Public License #
# as published by the Free Software Foundation - version 3, #
# or (at your option) any later version. #
# This program is distributed in the hope that it will be #
# useful, but WITHOUT ANY WARRANTY; without even the implied #
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR #
# PURPOSE. See the GNU General Public License in file COPYING #
# You should have received a copy of the GNU General Public #
# License along with this program; if not, write to the Free #
# Software Foundation, Inc., 51 Franklin Street, Fifth Floor, #
# Boston, MA 02111, USA #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Second Generation Pattern Database.
# New patterns that are not from patterns.db
##############################
# The patterns are classified into a number of different categories:
# Conn Connection patterns
# AS Antisuji patterns (i.e. prohibitted moves)
# Sente Followup moves (add followup or reverse_followup values)
# DD Double threat moves and defense against double threats
# Temp Temporary patterns to correct certain misbehaviours.
##############################
# FIXME: try to make callback_data pattern category specific
##############################
# Connection of one space jump
##############################
;odefend_against(*,a) && !oplay_attack(*,b) && !oplay_attack(*,c)
;oplay_attack(*,a,b,c,a) || oplay_attack(*,a,b,c,c)
.O.O indirect diagonal connection
;oplay_attack_either(*,a,b,c,a,c) && !oplay_defend_both(*,a,b,d,c,a,d)
;!oplay_break_through(*,a,*,b)
;oplay_attack(*,a,b,e,c,d,d)
O.* tiger's mouth connection
;odefend_against(*,a) && !oplay_attack(*,b) && !oplay_attack(*,c)
XO? far away connection, might leave much aji
?XO increase liberties to secure connection
XO* extend to secure connection
;oplay_attack_either(*,a,a,B)
..O very indirect connection
# gf New pattern. (3.7.1)
?.X kikashi to give bad shape before connecting
;oplay_attack_either(*,a,a,B)
# gf Revised constraint. (3.3.3)
;oplay_attack_either(*,a,b,c,a,c) && oplay_attack_either(*,b,a,e,b,e)
;&& oplay_defend_both(*,c,*,f)
# gf Revised constraint. (3.3.3)
;oplay_attack_either(*,a,b,c,a,c) && !oplay_defend_both(*,b,a,b,E)
;&& oplay_defend_both(*,c,*,f)
;oplay_attack_either(*,a,b,c,a,c) && oplay_attack_either(*,b,a,e,b,e)
;oplay_attack_either(*,a,b,c,a,c) && !oplay_defend_both(*,b,a,b,E)
;!oplay_defend_both(*,a,b,a,D) && oplay_attack_either(*,b,a,c,b,c)
;oplay_attack_either(*,a,b,c,a,c)
;!oplay_defend_both(*,a,b,a,E)
;oplay_attack_either(*,a,b,c,a,c) && oplay_attack_either(*,b,a,d,b,d)
;oplay_attack_either(*,a,a,B)
;oplay_attack_either(*,a,b,c,a,c) || oplay_attack_either(*,a,c,b,a,b)
;!oplay_break_through(*,a,b,c,b,*)
O*X cut through to connect
;!oplay_defend_both(*,A,B)
##############################################
# Connection of one space jump from two stones
##############################################
;oplay_attack_either(*,a,b,c,a,c)
;oplay_attack_either(*,a,b,c,a,c)
##############################
# Connection of two space jump
##############################
;!oplay_break_through(*,a,b,*,b,c)
;oplay_attack_either(*,a,b,c,d,e,c,e) && !oplay_defend_both(*,a,b,d,c,a,d)
;&& oplay_attack(*,b,a,c,c)
;oplay_attack_either(*,a,b,c,a,c)
;&& (oplay_attack(*,d,d) || oplay_attack_either(*,d,b,e,d,e))
# gf Revised constraint. (3.7.2)
;!oplay_disconnect(*,a,b)
;!oplay_defend_both(*,a,b,a,D) && !oplay_defend_both(*,b,a,c,b,c)
;oplay_attack(*,a,a) && oplay_attack(*,b,b)
;oplay_attack(*,a,a) && oplay_attack(*,b,b)
;&& !oplay_attack_either(*,b,a,*,a) && !oplay_attack_either(*,b,a,c,a)
# gf New pattern. (3.3.3)
;!oplay_disconnect(*,a,b)
; oplay_attack(*,a,b,c,a) && oplay_attack(*,A,B,C,A)
; && oplay_attack_either(*,b,a,d,b,d)
; && oplay_attack_either(*,B,A,D,B,D)
O*.. Block across large knight's move
;!oplay_defend_both(*,a,b,a,D) && oplay_attack_either(*,b,a,c,b,c)
;oplay_attack_either(*,a,b,c,d,e,c,e) && !oplay_defend_both(*,a,b,d,c,a,d)
;&& oplay_attack(*,b,a,c,c)
...o Block across large knight's move
;!oplay_break_through(*,a,b,*,b,c)
# gf New experimental pattern. Useful in nngs1:41. (3.1.30)
...o Block across large knight's move
;!oplay_disconnect(*,a,b)
;!oplay_break_through(*,a,b,*,b,e) && !oplay_defend_both(*,c,d,a,b,c,a)
;!oplay_break_through(*,a,b,*,b,d) && !oplay_defend(*,c,b,c)
;oplay_attack_either(*,a,b,c,a,c) && oplay_attack_either(*,b,a,d,b,d)
;oplay_attack_either(*,a,b,c,a,c)
;!oplay_break_through(*,a,b,*,b,c)
;!oplay_defend(*,a,b,c,d,a) && oplay_attack_either(*,c,a,b,d,e,b,e)
;oplay_attack(*,a,B) && !oplay_attack(*,c) && !oplay_attack(*,d)
;&& oplay_attack_either(*,e,B,e)
;oplay_attack_either(*,a,B,a) && !oplay_attack(*,c) && !oplay_attack(*,d)
##############################################
# Connection of two space jump from two stones
##############################################
;oplay_attack_either(*,a,b,c,a,c)
;!oplay_defend_both(*,a,b,a,C)
;oplay_attack_either(*,a,b,c,a,c) && oplay_attack(*,c,c)
;&& oplay_attack(*,b,a,c,D)
# This condition is not necessary but should be sufficient.
;oplay_attack(*,e,b,e) && !oplay_defend_both(*,b,a,c,d,b,c)
;&& !oplay_defend_both(*,d,c,a,b,d,a)
# This condition is not necessary but should be sufficient.
;!oplay_defend_both(*,b,a,c,d,b,c)
;&& !oplay_defend_both(*,d,c,a,b,d,a)
;!oplay_attack(*,a,b,d) && oplay_attack_either(*,a,b,c,a,c)
;oplay_attack_either(*,a,a,D) && oplay_attack_either(*,b,a,c,b,D)
;&& oplay_attack_either(*,b,a,e,b,D) && oplay_attack_either(*,b,a,d,e,c,b,c)
;!oplay_defend_both(*,a,b,a,D) && oplay_attack_either(*,b,a,c,b,c)
###########################
# Miscellaneous connections
###########################
;lib(a)>1 && lib(b)>1 && (lib(A)==2 || lib(B)==2)
;!oplay_attack_either(*,*,a)
;!xplay_attack_either(*,a,b,a)
# gf Pattern and constraint revised. (3.3.3)
;(alive(a) || alive(b)) && !xplay_disconnect(*,C,D) && !oplay_connect(*,C,D)
# gf New pattern. (3.5.3)
;!oplay_defend_both(*,a,b,C,D) && !oplay_connect(*,C,D)
#######################################
# Cut of one space jump from two stones
#######################################
;lib(e)==3 && xplay_attack_either(*,a,b,c,a,c)
;&& xplay_attack_either(*,a,b,d,a,d) && !xplay_defend(*,b,a,?,d,b)
;!xplay_break_through(*,a,b,*,b,E) && !xplay_attack(*,a,b,d,c,F)
#######################################
# Cut of two space jump from two stones
#######################################
###########################
# These are moves which are locally inferior or for some other reason
# should never be played. Obviously, a certain amount of care must be
# taken with these patterns.
###########################
# It's tempting to make this usually bad descent an antisuji, but
# sometimes descending is correct e.g. in the "comb formation"
# descending is the *only* move to live. So this should not be an antisuji.
# gf Reduced shape value. (3.5.2)
?XO don't defend by moving straight down if it gives X a free forcing move
;attack(b) && !oplay_attack(*,a,a) && oplay_attack(*,a,*)
?XO don't play double hane at the edge
;!oplay_attack(*,a,a) && oplay_attack(*,a,b,b)
OOX don't play potentially risky gote move
;!weak(A) && !weak(B) && oplay_attack(*,c,*)
# gf New pattern. (3.1.2)
|*O Connect without leaving bigger ko threat than necessary.
# gf New pattern. (3.1.3)
;oplay_attack(a,*,b,c,D,a)
# gf New pattern. (3.1.3)
|.O if legal, take ko before filling ko
;alive(b) && alive(C) && legal_omove(*)
# pp New pattern (3.3.18)
# (Work-around problem with NonTerritory11, see valuation of M19 in
# It is shape-penalized since it can probably be a semeai attack/defense
# in exceptionally rare cases. But actually it is really an antisuji.
?XX? don't play stupid zero point gote
; o_alive_somewhere(a,b) && o_alive_somewhere(c,d)
; && !oplay_attack(*,e,e)
; && (oplay_attack(*,e,*) || (o_somewhere(c) ? oplay_attack(*,e,c)
; : oplay_attack(*,e,d)))
###########################
# The purpose of these patterns is to give a value to the shape
###########################
# gf Revised constraint. (3.1.9)
# gf Revised constraint. (3.3.10)
OO empty triangle. Ok if the empty point of the triangle is an eye.
;!proper_eye(a) && !o_captures_something(*) && !x_captures_something(*)
# gf Revised constraint. (3.3.10)
O* empty triangle. Ok if the empty point of the triangle is an eye.
;!eye(a) && !o_captures_something(*)
# tm modified (3.1.23) (reduce shape penalty)
# see blunder:15, trevord:800
# gf Revised constraint. (3.3.17)
;!ko(*) && !o_captures_something(*)
*.O forcing move left behind
# gf Reduced shape value. (3.5.2)
?O.O protect against atari or threat to atari
# gf Added constraint. (3.1.15)
*.O classical good shape, unless it leaves a double atari
ooo don't give opponent ponnuki
; lib(e) > 1 && lib(f) > 1
; && (o_alive_somewhere(c) + o_alive_somewhere(C) + o_alive_somewhere(d) <= 1)
; && !(o_alive_somewhere(d) && (o_alive_somewhere(b) || o_alive_somewhere(B)))
# ab I don't understand this pattern. X has already played at LR of
# the pattern, so ponnuki is slow. Unless * attacks the eye space of X,
# I see no point in pulling this stone out.
ooo don't give opponent ponnuki
; (o_alive_somewhere(c) + o_alive_somewhere(C) + o_alive_somewhere(d) <= 1)
; && !(o_alive_somewhere(d) && (o_alive_somewhere(b) || o_alive_somewhere(B)))
; && !attack(e) && !attack(f)
ooo don't give opponent ponnuki
; (o_alive_somewhere(c) + o_alive_somewhere(C) + o_alive_somewhere(d) <= 1)
; && !(o_alive_somewhere(d) && (o_alive_somewhere(b) || o_alive_somewhere(B)))
; && !attack(A) && !attack(e) && !attack(f)
xXx force opponent into bad shape or ko
# gf Revised constraint. (3.1.3)
?..x Don't push from behind with few liberties (want to avoid double hane).
?..x Don't push from behind with few liberties (want to avoid double hane).
# gf Reduced shape value. (3.5.2)
..x Don't push from behind with few liberties if we have to bend after hane
;!oplay_attack_either(*,a,a,C) && oplay_attack(*,a,b,*)
# Such huge shape values can cause problems. See handtalk12.sgf, move 37
# (where * is actually an owl defense). -Arend
# gf Reduced shape value. (3.5.2)
?X? don't set up double cut
;!oplay_attack_either(*,a,b,c,a,c) && !oplay_attack_either(*,a,c,b,a,b) && !alive(B)
xXO? better connect solid at once than leaving a kikashi
;!oplay_attack(*,a,A) && !oplay_attack(*,a,B) && !oplay_attack(*,a,a)
xXO? better connect solid at once than leaving a kikashi
;!oplay_attack(*,a,A) && !oplay_attack(*,a,B) && !oplay_attack(*,a,a)
# gf Added constraint. (3.3.10)
# Usually better to capture if either stone in atari.
# The solid connection is better than nothing if the descent doesn't work
O*. X can still connect underneath
;!oplay_attack(*,a,a) && !oplay_attack(*,a,B) && !oplay_attack(*,a,C) && oplay_attack(a,*,*)
# gf Added n classification. (3.3.20)
;odefend_against(*,a) && (oplay_attack(*,b,b) || !oplay_attack(*,b,*))
# Negate shape bonus if X can force O to fill the tiger's mouth.
;lib(b)==2 && lib(C)>3 && !oplay_attack(*,a,a)
# Negate shape bonus if X can connect "beneath".
# gf New pattern. (3.1.4)
;oplay_attack(*,a,b,c,d,b) && lib(E)>3
# gf Revised constraint. (3.3.2)
;lib(B)>1 && xdefend_against(*,a)
# delta_moyo currently overvalues this move, so we compensate here
# gf Reduced shape value. (3.5.2)
# almost always best to capture immediately
;oplay_attack(*,a,b,c,d,*)
.OXx Usually better to connect solidly
# delta_terri should see the value of this move, but currently needs help
?X?? Usually better to connect solidly
# gf Reduced shape value. (3.5.2)
.*.X Don't cap with weak stone that can be cut off.
XO? Bad shape after atari on first line
;lib(b)==2 && !oplay_attack(*,a,a)
?XO? Bad shape after atari on first line
O.XO Avoid diagonal move that allows X to cut.
# gf Revised constraint. (3.1.20)
O.* Avoid setting up double threat.
;(!attack(b) || defend(b)) && !oplay_defend_both(*,a,*,b)
# In this position any move that defends the lower O stone will be
# assumed to break the connection, although X might connect
# underneath. Therefore we give some extra encourage to the real cut.
# If this move isn't safe, it won't be suggested anyway.
XOo Very seldom the right connection.
?O. Never bad to make an eye.
?X? Don't descend if we can (and have to) capture.
;lib(B)==1 && !oplay_attack(*,a,a)
OX.O Very inefficient move
;oplay_defend(*,B) && oplay_attack(*,a,*)
# Notice that this pattern gives one more shape point for the previous
# Sometimes the life and death code comes up with both this move and
# the more solid move one line higher. Prefer the latter.
?XO. usually better to connect solidly than leaving peep behind
# This pattern may be a little too general but is probably good.
?...? extend when faced with contact instability
# gf Added constraint. (3.1.3)
xxx? usually better to connect and block on third line
;!same_dragon(a,b) || x_alive_somewhere(C,D,E)
# gf Reduced shape value. (3.5.2)
?XXO blocking one step to the left usually much superior
;lib(b)>=3 && oplay_attack(a,*,*)
x.O too vulnerable to cutting
# gf Added constraint. (3.3.15)
# gf Revised pattern. (3.3.16)
.X. makes it harder for X to make eyes
OXx avoid descending if it leaves a kikashi
;oplay_attack(*,a,*) && !oplay_attack(*,a,a)
xO.xx connect after nozoki
O.. empty triangle on the edge
?X? good for eyespace and to avoid shortage of liberties
# gf Reduced shape value. (3.5.2)
O. don't force opponent to cut
?XO. don't defend by moving straight down if X can peep
..O avoid moves at cross purposes
# gf Reduced shape value. (3.5.2)
?X.O usually stupid, other atari or descent generally better
..O? don't connect this way because it leaves bad aji
# gf New pattern. (3.1.3)
..O? this connection on the other hand is usually good
# gf New pattern. (3.1.14)
..OX? usually we want to avoid this connection too
xX... connecting preferred to alternative defenses
O...x not so good shape on the edge
??xO. might connect, but horrible amounts of aji
# db increased negative shape (3.1.7)
# ab added ??? lines added as jump is often good on 3rd line
# gf This is way too general. Added constraint. (3.5.3)
xX. often bad to leave a gap
;oplay_disconnect(*,a,b,*,c)
# gf New pattern. (3.1.3)
?XX? when played as a ko threat, this is often inefficient
# gf New pattern. (3.1.3)
OXxx usually the right place for a small ko threat in this shape
# gf New pattern. (3.1.13)
?XXX?? usually the right way to strengthen the position
# gf New pattern. (3.1.14)
OX.. better to capture cleanly
# gf New pattern. (3.1.14)
?XO.. the descent leaves a peep
# gf New pattern. (3.1.14)
# gf Reduced shape value. (3.5.2)
?XO. don't leave double threat behind
;!oplay_defend_both(*,a,b,c)
# gf New pattern. (3.1.14)
?OO cancel empty triangle negative shape when we create an eye
# gf New pattern. (3.1.20)
# See strategy3:120. This pattern favors C7 to D8.
?OO some more shape if opponent could atari to destroy eye
# gf New pattern. (3.1.14)
o..? don't leave cutting points around
# gf New pattern. (3.1.15)
;(x_alive_somewhere(D) || oplay_attack(*,?,D,D)) && !oplay_defend(*,a,b,c,*)
# tm New Pattern. (3.1.16) (see trevor:220)
# gf Reduced shape value. (3.5.2)
; && oplay_attack(*,A,b,C,D)
; && oplay_attack(*,A,b,E,C,*)
# gf New pattern. (3.1.18) (see trevor:382)
# gf New pattern. (3.1.18) (see trevor:382)
# gf New pattern. (3.1.20) (see trevord:610,630,640)
OOo Almost always better to block on second line
# tm New Pattern (3.1.22) (see trevora:390)
# tm New Pattern (3.1.22) (see trevora:300)
# FIXME: potentially bad for ko threats.
# gf New pattern. (3.1.32) (see trevorb:280)
|XXO Prefer this as ko threat since it gives a second one
;!weak(A) && lib(A)==2 && xterri(b)
# gf New pattern. (3.3.3) (see trevorc:310)
*X? don't leave double atari behind
;!oplay_defend_both(*,c,a,b) && oplay_attack(d,c,c)
# gf New pattern. (3.3.3) (see trevorc:1310)
;lib(a)>1 && xlib(b)>1 && oplay_attack(*,b,*)
# gf New pattern. (3.3.10)
# Usually less aji when attacking at c rather than *.
;(xlib(*)==2 || (lib(a)>2 && xlib(*) < xlib(c)))
# gf New pattern. (3.3.15)
# Prefer cut to peep as ko threat.
# gf Revised constraint. (3.3.16)
;oplay_attack_either(*,A,B) && !safe_omove(*)
# gf New pattern. (3.5.3)
.OXx usually better to extend than atari in cross cut
;!dead(a) && !dead(b) && weak(a) && weak(b) && oplay_disconnect(*,a,b)
# gf New pattern. (3.7.2)
?X.X more potential for followup ko threats one step to the right
;lib(A)==2 && olib(*)==1 && olib(b)==1
###########################
# The purpose of these patterns is to give a rough estimate of the
# value of followup moves, either to this move or to moves the
# opponent could continue with if we do not defend now.
###########################
?X? Defend to avoid cutting points
;lib(B)>1 && xplay_attack(*,a)
*X? Capture to avoid cutting points
;lib(C)==1 && xplay_attack(a,b) && oplay_attack(*,a,a)
OX? Capture to avoid cutting points
;lib(C)==1 && xplay_attack(a,b) && oplay_attack(*,a,a)
# gf New pattern. (3.3.10)
?OX? Capture to avoid cutting points
;lib(C)==1 && xplay_attack(a,b) && oplay_attack(*,a,a)
.X. Defend to create cutting points
# Better to capture A or C at once if either in atari
;oplay_break_through(*,A,B,C) && lib(A)>1 && lib(C)>1
;oplay_attack_either(*,A,B) && !attack(B) && !attack(A)
# The followup value is usually larger in practice.
*XX force X to make dango
# The followup value is usually larger in practice.
XXX force X to make dango
# tm modified (3.1.22) (added oplay_defend)
;oplay_attack(*,A) && oplay_defend(*,A)
# FIXME: The followup value should be related to the size of A.
:8,-,followup(5),shape(1)
;lib(A)==3 && oplay_attack(*,A)
# gf Revised constraint. (3.1.20)
;lib(a) == 2 && !attack(a) && safe_xmove(*) && safe_omove(*)
# Action adds a reverse followup value.
# gf Revised constraint. (3.1.10)
# gf Revised constraint. (3.3.16)
# gf Revised constraint. (3.5.3)
;lib(a) == 2 && !attack(a) && olib(b) > 2 && safe_omove(*)
;&& (safe_xmove(*) || safe_xmove(b))
;&& (oplay_attack(*,b,b)==WIN
; || (x_somewhere(c) && oplay_attack_either(*,b,b,c)))
# Action adds a reverse followup value.
# gf New pattern. (3.3.16)
;lib(a) == 2 && !attack(a) && safe_omove(*)
;&& (safe_xmove(b) || safe_xmove(c))
;&& oplay_attack(*,b,b)==WIN
;&& oplay_attack(*,c,c)==WIN
# Action adds a reverse followup value.
# gf New pattern. (3.3.17)
;lib(a) == 2 && !attack(a) && safe_omove(*)
;&& !oplay_defend(*,b,c,b)
# Action adds a reverse followup value.
# gf New pattern. (3.7.4)
# gf Removed O classification and revised constraint. (3.7.10)
;alive(a) && lib(a) == 2 && !attack(a) && olib(b) > 2 && safe_omove(*)
;&& safe_xmove(b) && oplay_attack(*,b,b)==WIN
# Action adds a reverse followup value.
:8,OX,reverse_followup(5)
;lib(a)>1 && !attack(B) && !attack(C) && xlib(d)>1
;lib(a)>1 && o_alive_somewhere(e,f,g) && !attack(B) && !attack(C)
;&& !oplay_defend_both(*,?,d,B,C)
# gf New pattern. (3.1.14)
# The constraint is unprecise, but correcting it probably
# require a handwritten helper.
:8,OX,reverse_followup(5)
;xplay_attack(*,a,b,*) && xplay_defend_both(*,a,b,*,b)
# gf New pattern. (3.1.15)
;alive(d) && !xplay_defend_both(*,a,b,?,c,a,d)
# gf New pattern. (3.3.13)
# The reverse followup value is probably often bigger than 5 points.
;omoyo_opposite(a) && alive(b) && alive(C)
# gf New pattern. (3.3.16)
# Usually underestimating the reverse followup, but better than nothing.
:8,OX,reverse_followup(1)
;((!o_somewhere(b) && oterri(b))
; || (!o_somewhere(c) && oterri(c)))
;&& safe_xmove(*) && !xplay_attack(*,a,*)
# gf New pattern. (3.3.16)
# Usually underestimating the reverse followup, but better than nothing.
:8,OX,reverse_followup(2)
;oterri(b) && oterri(c) && safe_xmove(*) && !xplay_attack(*,a,*)
# gf New pattern. (3.3.16)
# Usually underestimating the reverse followup, but better than nothing.
:8,OX,reverse_followup(3)
;oterri(b) && oterri(c) && oterri(d) && safe_xmove(*) && !xplay_attack(*,a,*)
# pp New pattern, see trevord:950 (3.3.20)
; oplay_attack(*,A) && oplay_attack(*,a,A) && oplay_attack(*,b,a,A)
> good_attack_threat(*,A)
# gf New pattern. (3.5.4)
;lib(a)>3 && alive(B) && xplay_attack(*,c)
>prevent_attack_threat(c);
:8,OX,reverse_followup(8)
; lib(A)==3 && safe_xmove(*) && !xplay_defend(*,?,b,A)
########################################################
# Double threat moves and defense against double threats
########################################################
# FIXME: This isn't really double atari - just plain old
# capture also matches here. see nngs:1260
>test_attack_either_move(A,B)
;!xplay_defend_both(*,a,b)
>add_defend_both_move(a,b);
*.O double atari on me, defended by hanging connection
;!xplay_defend_both(c,a,b)
;&& (oplay_attack(*,c,c) || oplay_defend_both(*,c,a,b))
>add_defend_both_move(a,b);
;oplay_attack(*,D) && oplay_attack_either(*,a,D,E)
;&& !oplay_defend_both(*,b,c,D,E)
>test_attack_either_move(D,E)
# gf Revised constraint. (3.5.2)
;xplay_attack(a,d) && xplay_attack_either(a,*,d,e)
;&& !xplay_defend_both(a,b,c,d,e) && !xplay_defend_both(a,c,b,d,e)
;&& !xplay_connect(a,d,e) && oplay_connect(*,a,d,e)
>add_defend_both_move(d,e);
# gf Exclude this pattern when scoring. (3.3.14)
# This is somewhat wimpy. We should do more exact reading to verify
# whether it really is necessary.
;&& lib(c)<=4 && xplay_attack(a,b) && safe_xmove(a) && odefend_against(*,a)
>add_defend_both_move(b,c);
# al1 Revised symmetry. (3.7.11)
>test_attack_either_move(A,B)
# gf Revised constraint. (3.1.20)
;lib(d)<4 && (xlib(*)>1 || lib(d)<3)
;&& oplay_defend(*,A) && oplay_defend(*,B)
>test_attack_either_move(A,B)
;safe_xmove(a) && !xplay_defend_both(a,b,c) && oplay_defend_both(*,a,b,c)
>add_defend_both_move(b,c);
# gf Added constraint. (3.3.20)
# Not a problem if the opponent can't even threaten to cut after the move.
;oplay_disconnect(*,a,*,b)
;safe_xmove(a) && !xplay_defend_both(a,b,c) && oplay_defend_both(*,a,b,c)
>add_defend_both_move(b,c);
*O. generalized tsukenobi joseki
;&& safe_xmove(a)==WIN && !xplay_defend_both(a,b,c) && oplay_attack(*,a,a)==WIN
>add_defend_both_move(b,c);
; !attack(A) && !attack(B) && oplay_attack(*,A) && oplay_attack(*,B)
>test_attack_either_move(A,B)
;lib(A)==3 && !oplay_attack(*,E) && oplay_attack(*,d,A)
;&& !oplay_defend_both(*,c,d,A,B)
>test_attack_either_move(A,B)
;lib(a)==3 && !attack(e) && xplay_attack(*,d,a)
;&& !xplay_defend_both(*,c,d,a,b)
>add_defend_both_move(a,b)
###########################
# Temporary patterns to correct certain misbehaviours.
###########################
# This joseki is played far too frequently.
# existed since at least 3.0.0
# Don't make a short jump along the edge before shimari.
# existed since at least 3.0.0
# Don't make a short extension from san-san in open surroundings.
# existed since at least 3.0.0
# Don't make a one space jump along the edge when there is room for a
# existed since at least 3.0.0
# FIXME: consider using replace instead of antisuji here?
# existed since at least 3.1.20
;!weak(G) && x_alive_somewhere(a,b,c,d,e,f)
# existed since at least 3.1.20
# gf New pattern. (3.3.6)
# ab Modified: ok after approach move (3.7.1)
|............ don't play halfways between hoshi