github.com/joshprzybyszewski/masyu@v0.0.0-20230508015604-f31a025f6e7e/solve/rule_default_test.go (about)

     1  package solve
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/joshprzybyszewski/masyu/model"
     7  	"github.com/stretchr/testify/assert"
     8  )
     9  
    10  func TestRuleDefault(t *testing.T) {
    11  
    12  	const (
    13  		right uint8 = 1 << iota
    14  		down
    15  		left
    16  		up
    17  
    18  		none uint8 = 0
    19  		all        = right | down | left | up
    20  	)
    21  
    22  	testCases := []struct {
    23  		name        string
    24  		startLines  uint8
    25  		startAvoids uint8
    26  		expInvalid  bool
    27  		expLines    uint8
    28  		expAvoids   uint8
    29  	}{{
    30  		name: `none set`,
    31  	}, {
    32  		name:       `one line: right`,
    33  		startLines: right,
    34  		expLines:   right,
    35  	}, {
    36  		name:       `one line: down`,
    37  		startLines: down,
    38  		expLines:   down,
    39  	}, {
    40  		name:       `one line: left`,
    41  		startLines: left,
    42  		expLines:   left,
    43  	}, {
    44  		name:       `one line: up`,
    45  		startLines: up,
    46  		expLines:   up,
    47  	}, {
    48  		name:        `one avoid: right`,
    49  		startAvoids: right,
    50  		expAvoids:   right,
    51  	}, {
    52  		name:        `one avoid: down`,
    53  		startAvoids: down,
    54  		expAvoids:   down,
    55  	}, {
    56  		name:        `one avoid: left`,
    57  		startAvoids: left,
    58  		expAvoids:   left,
    59  	}, {
    60  		name:        `one avoid: up`,
    61  		startAvoids: up,
    62  		expAvoids:   up,
    63  	}, {
    64  		name:        `one lines and one avoid: right & down`,
    65  		startLines:  right,
    66  		startAvoids: down,
    67  		expLines:    right,
    68  		expAvoids:   down,
    69  	}, {
    70  		name:        `one lines and one avoid: right & left`,
    71  		startLines:  right,
    72  		startAvoids: left,
    73  		expLines:    right,
    74  		expAvoids:   left,
    75  	}, {
    76  		name:        `one lines and one avoid: right & up`,
    77  		startLines:  right,
    78  		startAvoids: up,
    79  		expLines:    right,
    80  		expAvoids:   up,
    81  	}, {
    82  		name:        `one lines and one avoid: down & left`,
    83  		startLines:  down,
    84  		startAvoids: left,
    85  		expLines:    down,
    86  		expAvoids:   left,
    87  	}, {
    88  		name:        `one lines and one avoid: down & up`,
    89  		startLines:  down,
    90  		startAvoids: up,
    91  		expLines:    down,
    92  		expAvoids:   up,
    93  	}, {
    94  		name:        `one lines and one avoid: left & up`,
    95  		startLines:  left,
    96  		startAvoids: up,
    97  		expLines:    left,
    98  		expAvoids:   up,
    99  	}, {
   100  		name:       `two lines: right & down`,
   101  		startLines: right | down,
   102  		expLines:   right | down,
   103  		expAvoids:  left | up,
   104  	}, {
   105  		name:       `two lines: right & left`,
   106  		startLines: right | left,
   107  		expLines:   right | left,
   108  		expAvoids:  down | up,
   109  	}, {
   110  		name:       `two lines: right & up`,
   111  		startLines: right | up,
   112  		expLines:   right | up,
   113  		expAvoids:  down | left,
   114  	}, {
   115  		name:       `two lines: down & left`,
   116  		startLines: down | left,
   117  		expLines:   down | left,
   118  		expAvoids:  up | right,
   119  	}, {
   120  		name:       `two lines: down & up`,
   121  		startLines: down | up,
   122  		expLines:   down | up,
   123  		expAvoids:  left | right,
   124  	}, {
   125  		name:       `two lines: left & up`,
   126  		startLines: left | up,
   127  		expLines:   left | up,
   128  		expAvoids:  down | right,
   129  	}, {
   130  		name:        `two Avoids: right & down`,
   131  		startAvoids: right | down,
   132  		expAvoids:   right | down,
   133  	}, {
   134  		name:        `two Avoids: right & left`,
   135  		startAvoids: right | left,
   136  		expAvoids:   right | left,
   137  	}, {
   138  		name:        `two Avoids: right & up`,
   139  		startAvoids: right | up,
   140  		expAvoids:   right | up,
   141  	}, {
   142  		name:        `two Avoids: down & left`,
   143  		startAvoids: down | left,
   144  		expAvoids:   down | left,
   145  	}, {
   146  		name:        `two Avoids: down & up`,
   147  		startAvoids: down | up,
   148  		expAvoids:   down | up,
   149  	}, {
   150  		name:        `two Avoids: left & up`,
   151  		startAvoids: left | up,
   152  		expAvoids:   left | up,
   153  	}, {
   154  		name:        `one line and two Avoids: left vs. right & down`,
   155  		startLines:  left,
   156  		startAvoids: right | down,
   157  		expLines:    left | up,
   158  		expAvoids:   right | down,
   159  	}, {
   160  		name:        `one line and two Avoids: up vs. right & down`,
   161  		startLines:  up,
   162  		startAvoids: right | down,
   163  		expLines:    left | up,
   164  		expAvoids:   right | down,
   165  	}, {
   166  		name:        `one line and two Avoids: down vs. right & left`,
   167  		startLines:  down,
   168  		startAvoids: right | left,
   169  		expLines:    up | down,
   170  		expAvoids:   right | left,
   171  	}, {
   172  		name:        `one line and two Avoids: up vs. right & left`,
   173  		startLines:  up,
   174  		startAvoids: right | left,
   175  		expLines:    up | down,
   176  		expAvoids:   right | left,
   177  	}, {
   178  		name:        `one line and two Avoids: left vs. right & up`,
   179  		startLines:  left,
   180  		startAvoids: right | up,
   181  		expLines:    left | down,
   182  		expAvoids:   right | up,
   183  	}, {
   184  		name:        `one line and two Avoids: down vs. right & up`,
   185  		startLines:  down,
   186  		startAvoids: right | up,
   187  		expLines:    left | down,
   188  		expAvoids:   right | up,
   189  	}, {
   190  		name:        `one line and two Avoids: right vs. down & left`,
   191  		startLines:  right,
   192  		startAvoids: down | left,
   193  		expLines:    up | right,
   194  		expAvoids:   down | left,
   195  	}, {
   196  		name:        `one line and two Avoids: up vs. down & left`,
   197  		startLines:  up,
   198  		startAvoids: down | left,
   199  		expLines:    up | right,
   200  		expAvoids:   down | left,
   201  	}, {
   202  		name:        `one line and two Avoids: left vs. down & up`,
   203  		startLines:  left,
   204  		startAvoids: down | up,
   205  		expLines:    left | right,
   206  		expAvoids:   down | up,
   207  	}, {
   208  		name:        `one line and two Avoids: right vs. down & up`,
   209  		startLines:  right,
   210  		startAvoids: down | up,
   211  		expLines:    left | right,
   212  		expAvoids:   down | up,
   213  	}, {
   214  		name:        `one line and two Avoids: right vs. left & up`,
   215  		startLines:  right,
   216  		startAvoids: left | up,
   217  		expLines:    down | right,
   218  		expAvoids:   left | up,
   219  	}, {
   220  		name:        `one line and two Avoids: down vs. left & up`,
   221  		startLines:  down,
   222  		startAvoids: left | up,
   223  		expLines:    down | right,
   224  		expAvoids:   left | up,
   225  	}, {
   226  		name:        `one avoid and two lines: left vs. right & down`,
   227  		startAvoids: left,
   228  		startLines:  right | down,
   229  		expLines:    right | down,
   230  		expAvoids:   left | up,
   231  	}, {
   232  		name:        `one avoid and two lines: up vs. right & down`,
   233  		startAvoids: up,
   234  		startLines:  right | down,
   235  		expLines:    right | down,
   236  		expAvoids:   left | up,
   237  	}, {
   238  		name:        `one avoid and two lines: down vs. right & left`,
   239  		startAvoids: down,
   240  		startLines:  right | left,
   241  		expLines:    right | left,
   242  		expAvoids:   up | down,
   243  	}, {
   244  		name:        `one avoid and two lines: up vs. right & left`,
   245  		startAvoids: up,
   246  		startLines:  right | left,
   247  		expLines:    right | left,
   248  		expAvoids:   up | down,
   249  	}, {
   250  		name:        `one avoid and two lines: left vs. right & up`,
   251  		startAvoids: left,
   252  		startLines:  right | up,
   253  		expLines:    right | up,
   254  		expAvoids:   left | down,
   255  	}, {
   256  		name:        `one avoid and two lines: down vs. right & up`,
   257  		startAvoids: down,
   258  		startLines:  right | up,
   259  		expLines:    right | up,
   260  		expAvoids:   left | down,
   261  	}, {
   262  		name:        `one avoid and two lines: right vs. down & left`,
   263  		startAvoids: right,
   264  		startLines:  down | left,
   265  		expLines:    down | left,
   266  		expAvoids:   up | right,
   267  	}, {
   268  		name:        `one avoid and two lines: up vs. down & left`,
   269  		startAvoids: up,
   270  		startLines:  down | left,
   271  		expLines:    down | left,
   272  		expAvoids:   up | right,
   273  	}, {
   274  		name:        `one avoid and two lines: left vs. down & up`,
   275  		startAvoids: left,
   276  		startLines:  down | up,
   277  		expLines:    down | up,
   278  		expAvoids:   left | right,
   279  	}, {
   280  		name:        `one avoid and two lines: right vs. down & up`,
   281  		startAvoids: right,
   282  		startLines:  down | up,
   283  		expLines:    down | up,
   284  		expAvoids:   left | right,
   285  	}, {
   286  		name:        `one avoid and two lines: right vs. left & up`,
   287  		startAvoids: right,
   288  		startLines:  left | up,
   289  		expLines:    left | up,
   290  		expAvoids:   down | right,
   291  	}, {
   292  		name:        `one avoid and two lines: down vs. left & up`,
   293  		startAvoids: down,
   294  		startLines:  left | up,
   295  		expLines:    left | up,
   296  		expAvoids:   down | right,
   297  	}, {
   298  		name:       `three lines: RDL`,
   299  		startLines: right | down | left,
   300  		expInvalid: true,
   301  	}, {
   302  		name:       `three lines: RDU`,
   303  		startLines: right | down | up,
   304  		expInvalid: true,
   305  	}, {
   306  		name:       `three lines: RLU`,
   307  		startLines: right | left | up,
   308  		expInvalid: true,
   309  	}, {
   310  		name:       `three lines: DLU`,
   311  		startLines: down | left | up,
   312  		expInvalid: true,
   313  	}, {
   314  		name:        `three Avoids: RDL`,
   315  		startAvoids: right | down | left,
   316  		expAvoids:   all,
   317  	}, {
   318  		name:        `three Avoids: RDU`,
   319  		startAvoids: right | down | up,
   320  		expAvoids:   all,
   321  	}, {
   322  		name:        `three Avoids: RLU`,
   323  		startAvoids: right | left | up,
   324  		expAvoids:   all,
   325  	}, {
   326  		name:        `three Avoids: DLU`,
   327  		startAvoids: down | left | up,
   328  		expAvoids:   all,
   329  	}, {
   330  		name:       `four lines: RDLU`,
   331  		startLines: all,
   332  		expInvalid: true,
   333  	}, {
   334  		name:        `four avoid: RDLU`,
   335  		startAvoids: all,
   336  		expAvoids:   all,
   337  	}}
   338  
   339  	for _, tc := range testCases {
   340  		tc := tc
   341  		t.Run(tc.name, func(t *testing.T) {
   342  			s := newState(
   343  				6,
   344  				nil,
   345  			)
   346  			c := model.Coord{
   347  				Row: 3,
   348  				Col: 3,
   349  			}
   350  
   351  			if tc.startLines&right == right {
   352  				s.lineHor(c.Row, c.Col)
   353  			}
   354  			if tc.startAvoids&right == right {
   355  				s.avoidHor(c.Row, c.Col)
   356  			}
   357  
   358  			if tc.startLines&down == down {
   359  				s.lineVer(c.Row, c.Col)
   360  			}
   361  			if tc.startAvoids&down == down {
   362  				s.avoidVer(c.Row, c.Col)
   363  			}
   364  
   365  			if tc.startLines&left == left {
   366  				s.lineHor(c.Row, c.Col-1)
   367  			}
   368  			if tc.startAvoids&left == left {
   369  				s.avoidHor(c.Row, c.Col-1)
   370  			}
   371  
   372  			if tc.startLines&up == up {
   373  				s.lineVer(c.Row-1, c.Col)
   374  			}
   375  			if tc.startAvoids&up == up {
   376  				s.avoidVer(c.Row-1, c.Col)
   377  			}
   378  
   379  			assert.Equal(t, tc.startLines|tc.startAvoids != 0, s.rules.hasPending)
   380  
   381  			ss := settle(&s)
   382  
   383  			if tc.expInvalid {
   384  				assert.Equal(t, invalid, ss)
   385  				return
   386  			}
   387  			assert.False(t, s.rules.hasPending)
   388  			assert.Equal(t, validUnsolved, ss)
   389  
   390  			l, a := s.horAt(c.Row, c.Col)
   391  			assert.Equal(t, tc.expLines&right == right, l, `right should be a Line`)
   392  			assert.Equal(t, tc.expAvoids&right == right, a, `right should be an Avoid`)
   393  
   394  			l, a = s.verAt(c.Row, c.Col)
   395  			assert.Equal(t, tc.expLines&down == down, l, `down should be a Line`)
   396  			assert.Equal(t, tc.expAvoids&down == down, a, `down should be an Avoid`)
   397  
   398  			l, a = s.horAt(c.Row, c.Col-1)
   399  			assert.Equal(t, tc.expLines&left == left, l, `left should be a Line`)
   400  			assert.Equal(t, tc.expAvoids&left == left, a, `left should be an Avoid`)
   401  
   402  			l, a = s.verAt(c.Row-1, c.Col)
   403  			assert.Equal(t, tc.expLines&up == up, l, `up should be a Line`)
   404  			assert.Equal(t, tc.expAvoids&up == up, a, `up should be an Avoid`)
   405  		})
   406  	}
   407  }