Monday, September 4, 2017

Your Random May Vary


At the beginning of the summer, we started hosting a semi-monthly Dungeons and Dragons game at our house. It's typically a lot of fun, involving much role-playing and dice rolling. We share Dungeon-Mastering duties; I think I've run most of the sessions, but at least two or three have been run by someone else. When I'm running the game, my character is typically an NPC. It's a bit of a shame, because my stats are pretty awesome.

I got to thinking this morning... I rolled my current character (as all my characters), using real dice and a "roll-4-keep-3" approach. I roll four 6-sided dice, discarding the lowest, and summing the other three. I do that six times in a row, and I've got the stats block for a new character.

I never use anything but real dice unless I happen not to have a set (and fyi: I carry a couple of sets around in my backpack just in case a spontaneous or random one-shot happens). Garrett used to roll great stats very often using his IPhone dice, and tended to roll challenges really highly as well. I started thinking about the difference in our results and decided to mess around with a rolling app this morning.

It's been a while since I posted anything technical. Bear with me.

I started by creating a little app that would roll a six-sided dice for me.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
(ns stats-generator.main
  (:gen-class))

(def d6 [1 2 3 4 5 6])

(defn roll-d6 []
  (rand-nth d6))

(defn -main
  "I don't do a whole lot ... yet."
  [& args]
  (println "Hello, World!"))

I quickly realized that I didn't quite know where to go. TDD to the rescue!

1
2
3
4
5
6
(ns stats-generator.main-test
  (:require [clojure.test :refer :all]
            [stats-generator.main :as main]))

(deftest test-roll-4-keep-3
  (testing "Given a roll of 4 6-sided dice, sums the highest 3"))

I started with a description of one of the end goals: a function that would roll four dice and keep the highest three. That... is probably too broad. Let's decompose for a moment. We know we'll need to roll four 6-sided dice and drop the lowest roll. Maybe that dropping function is easier to test and implement.

1
2
3
4
5
(deftest test-drop-lowest
  (testing "Given all different values, drops the lowest"
    (let [v [1 2 3 4]
          expected [2 3 4]]
      (is (= expected (main/drop-lowest v))))))

There's the test; we should stub a red (failing) function.

1
2
3
4
(defn drop-lowest
  "Given a vector, returns a vector sans its lowest value."
  [v]
  v)

Done! Run the tests!

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
(run-tests)

Testing stats-generator.main-test

FAIL in (test-drop-lowest) (main_test.clj:9)
Given all different values, drops the lowest
expected: [2 3 4]
  actual: [1 2 3 4]
    diff: - [2 3 4]
          + [1 2 3 4]

Ran 2 tests containing 1 assertions.
1 failures, 0 errors.
=> {:test 2, :pass 0, :fail 1, :error 0, :type :summary}

Failed as expected. What's a simple solution that will work?

1
2
3
4
(defn drop-lowest
  "Given a vector, returns a vector sans its lowest value."
  [v]
  (rest (sort v)))

Seems reasonable. Tests tell us...?

1
2
3
4
5
6
7
(run-tests)

Testing stats-generator.main-test

Ran 2 tests containing 1 assertions.
0 failures, 0 errors.
=> {:test 2, :pass 1, :fail 0, :error 0, :type :summary}

Yay! Green tests! Let's fill in some other assertions to make sure we're not fooling ourselves.

1
2
3
4
5
6
7
8
9
(deftest test-drop-lowest
  (testing "Given all different values in random order, drops the lowest"
    (is (= [2 3 4] (main/drop-lowest [1 2 3 4])))
    (is (= [2 3 4] (main/drop-lowest [4 2 3 1]))))
  (testing "Given identical values, drops one of them"
    (is (= [1 1 1] (main/drop-lowest [1 1 1 1]))))
  (testing "Given some duplicated values, drops whatever's lowest"
    (is (= [2 2 3] (main/drop-lowest [2 3 2 2])))
    (is (= [5 6 6] (main/drop-lowest [5 6 4 6])))))

That's good enough. A question I'm often asked is "how much automated test coverage should I implement?" The pedantic answer is "100%," but the pragmatic answer is "as much as you can that covers stuff you would do by hand anyway." That's my rule-of-thumb, in any case. Sometimes I do more, sometimes less. But if I find bugs, I try to reproduce them with tests and then they're covered into perpetuity. As such the test coverage grows organically.

Alright, let's fill in some more of the decomposed functions and see where we wind up.

 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
(ns stats-generator.main
  (:gen-class))

(def d6 [1 2 3 4 5 6])

(defn roll-d6 [_]
  (rand-nth d6))

(defn roll-4
  "Rolls a d6 4 times"
  []
  (map roll-d6 (range 4)))

(defn drop-lowest
  "Given a vector, returns a vector sans its lowest value."
  [v]
  (rest (sort v)))

(defn sum [v]
  (apply + v))

(defn roll-4-keep-3
  "Rolls a 6-sided die 4 times, summing the highest 3 values"
  []
  (-> (roll-4)
      (drop-lowest)
      (sum)))

(defn -main
  "I don't do a whole lot ... yet."
  [& args]
  (println "Hello, World!"))

That seems reasonable. Test coverage is minimal, but enough for me to know that I'm not doing something overtly silly.

 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
(ns stats-generator.main-test
  (:require [clojure.test :refer :all]
            [stats-generator.main :as main]))

(deftest test-roll-4
  (let [roll (main/roll-4)]
    (is (= 4 (count roll)))
    (is (every? #(<= 1 % 6) roll))))

(deftest test-drop-lowest
  (testing "Given all different values in random order, drops the lowest"
    (is (= [2 3 4] (main/drop-lowest [1 2 3 4])))
    (is (= [2 3 4] (main/drop-lowest [4 2 3 1]))))
  (testing "Given identical values, drops one of them"
    (is (= [1 1 1] (main/drop-lowest [1 1 1 1]))))
  (testing "Given some duplicated values, drops whatever's lowest"
    (is (= [2 2 3] (main/drop-lowest [2 3 2 2])))
    (is (= [5 6 6] (main/drop-lowest [5 6 4 6])))))

(deftest test-sum
  (is (= 18 (main/sum [6 6 6])))
  (is (= 3 (main/sum [1 1 1])))
  (is (= 12 (main/sum [3 4 5]))))

(deftest test-roll-4-keep-3
  (testing "Given a roll of 4 6-sided dice, sums the highest 3"
    (is (<= 3 (main/roll-4-keep-3) 18))))

At this point, I'm ready to do the REAL implementation. We'll set up a little recursion to see if we can generate a set of six 18s. I'm not good at math, but the likelihood seems pretty low that I'll actually do it. Let's compromise and try 100 MILLION times. We'll also squawk if we get close.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
(defn roll-all-18s []
 (let [counter (atom 0)]
   (println "STARTED AT:" (now))
    (loop [current-roll []]
      (swap! counter inc)
      (cond
        (= 100000000 @counter)
        (do
          (println "Gave up after ONE HUNDRED MILLION sets...")
          (println "ENDED AT:" (now)))

        (= [18 18 18 18 18 18] current-roll)
        (do
          (println "All 18s took" @counter "attempt(s).")
          (println "ENDED AT:" (now)))

        :default
        (do
          (when (<= 5 (count (filter #(= 18 %) current-roll)))
            (println "close call!" current-roll))
          (recur (roll-stats)))))))

Alrighty! We can run this in the REPL. The first try's results follow.

1
2
3
4
5
(roll-all-18s)
STARTED AT: #inst "2017-09-04T17:26:34.981-00:00"
close call! (5 18 18 18 18 18)
Gave up after ONE HUNDRED MILLION sets...
ENDED AT: #inst "2017-09-04T17:44:07.983-00:00"

It took us 22 minutes to try 100 MILLION times, and in all those tries, we only got close once. The frequency lines up with my (admittedly bad-at-math-and-fuzzy) expectations.

So how in the world did Garrett's IPhone roll so well for him so often? I suspect they weren't using the same approach as I was (roll-4-keep-3). After a little more research, I found that another approach that simply took a random integer between 3 and 18. This seemed like a pretty simple and probably more efficient implementation, but I suspected that the level of randomness in that picking was LOWER than that of the roll-4-take-3 approach. Again, I don't have the math or computer science to tell you why -- it was just my instinct.

So, I implemented a couple more rolling functions...

1
2
3
4
(def range-3-18 (range 3 19))

(defn roll-d3-18 [_]
  (rand-nth range-3-18))

...and refactored the roll-stats function into a multi-method that dispatches on the roll style you wanted to use.

1
2
3
4
5
6
7
8
9
(defmulti roll-stats identity)

(defmethod roll-stats :roll-4-keep-3
  [_]
  (map roll-4-keep-3 (range 6)))

(defmethod roll-stats :range-3-to-18
  [_]
  (map roll-d3-18 (range 6)))

No tests were added. I wanted to get to the bottom of this silly thing. Let's do some more REPLing!

 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
(roll-all-18s :range-3-to-18)
STARTED AT: #inst "2017-09-04T21:56:32.650-00:00"
close call! (18 12 18 18 18 18)
close call! (18 18 17 18 18 18)
close call! (18 18 18 18 18 10)
close call! (18 18 18 18 17 18)
close call! (18 18 18 18 12 18)
close call! (18 18 18 18 18 7)
close call! (18 18 18 9 18 18)
close call! (18 18 18 17 18 18)
close call! (18 18 18 18 8 18)
close call! (18 13 18 18 18 18)
close call! (18 9 18 18 18 18)
close call! (18 18 14 18 18 18)
close call! (18 18 18 4 18 18)
close call! (18 18 18 18 12 18)
close call! (18 18 18 18 10 18)
close call! (18 18 18 18 18 3)
close call! (18 3 18 18 18 18)
close call! (18 18 18 18 10 18)
close call! (18 18 10 18 18 18)
close call! (18 18 18 18 18 3)
close call! (18 18 18 18 15 18)
close call! (18 18 15 18 18 18)
close call! (18 18 18 18 12 18)
close call! (18 18 18 11 18 18)
close call! (3 18 18 18 18 18)
close call! (18 18 15 18 18 18)
close call! (18 18 18 9 18 18)
close call! (18 18 18 18 18 7)
close call! (17 18 18 18 18 18)
close call! (18 18 18 18 15 18)
close call! (18 18 18 18 11 18)
close call! (18 17 18 18 18 18)
close call! (18 4 18 18 18 18)
close call! (18 18 16 18 18 18)
close call! (18 18 18 8 18 18)
close call! (18 18 18 18 9 18)
close call! (18 18 15 18 18 18)
close call! (9 18 18 18 18 18)
close call! (18 18 18 18 7 18)
close call! (18 11 18 18 18 18)
close call! (18 18 18 6 18 18)
close call! (18 18 18 18 8 18)
close call! (18 18 18 15 18 18)
close call! (18 18 18 18 18 9)
close call! (18 18 9 18 18 18)
close call! (18 18 18 18 4 18)
close call! (18 18 18 18 11 18)
close call! (7 18 18 18 18 18)
close call! (18 18 18 18 18 3)
close call! (18 11 18 18 18 18)
close call! (18 18 12 18 18 18)
close call! (18 18 18 5 18 18)
close call! (18 18 18 18 18 6)
close call! (18 17 18 18 18 18)
close call! (18 6 18 18 18 18)
close call! (18 18 18 9 18 18)
close call! (18 18 18 11 18 18)
close call! (18 11 18 18 18 18)
close call! (18 16 18 18 18 18)
close call! (14 18 18 18 18 18)
close call! (18 18 10 18 18 18)
close call! (18 18 18 18 18 12)
close call! (18 18 18 18 18 16)
close call! (18 18 18 4 18 18)
close call! (18 18 18 18 12 18)
close call! (18 11 18 18 18 18)
close call! (18 18 18 18 16 18)
close call! (18 18 5 18 18 18)
close call! (18 18 18 18 18 16)
close call! (18 18 18 17 18 18)
close call! (5 18 18 18 18 18)
close call! (18 18 18 11 18 18)
close call! (18 18 18 18 18 12)
close call! (18 18 18 18 18 7)
close call! (18 18 18 3 18 18)
close call! (18 18 18 18 8 18)
close call! (18 18 18 5 18 18)
close call! (15 18 18 18 18 18)
close call! (18 5 18 18 18 18)
close call! (18 18 18 16 18 18)
close call! (18 18 18 18 4 18)
close call! (18 18 17 18 18 18)
close call! (18 14 18 18 18 18)
close call! (18 18 18 18 18 7)
close call! (18 18 18 4 18 18)
close call! (18 18 18 18 4 18)
All 18s took 13880334 attempt(s).
ENDED AT: #inst "2017-09-04T21:57:12.554-00:00"

WHOA! There were a TON more close calls, and an actual hit about 14 milllion rolls in.

I decided to re-run the roll-4-take-3 strategy to verify its performance.

1
2
3
4
5
6
7
(roll-all-18s :roll-4-keep-3)
STARTED AT: #inst "2017-09-04T22:51:37.468-00:00"
close call! (18 18 18 18 14 18)
close call! (13 18 18 18 18 18)
close call! (18 18 18 18 18 9)
Gave up after ONE HUNDRED MILLION sets...
ENDED AT: #inst "2017-09-04T23:09:02.571-00:00"

A few more close calls were had, but roughly the same result. I re-ran the range-3-to-18 strategy:

1
2
3
4
5
6
(roll-all-18s :range-3-to-18)
STARTED AT: #inst "2017-09-04T23:24:08.765-00:00"
close call! (18 18 8 18 18 18)
close call! (18 18 18 5 18 18)
All 18s took 321349 attempt(s).
ENDED AT: #inst "2017-09-04T23:24:09.925-00:00"

Wowzers. SO MUCH MORE LIKELY to roll 18s using that approach. The second run only took a second and slightly more than 321,000 tries.

So, what's the moral of the story? I think it's that the amount of randomness you get from computers may vary, based on what the underlying strategy is. Random numbers aren't truly random in the machine. Always keep that in mind when they rise up and become our overlords.

Also: rolling 321,000 times by hand, at one set of rolls per second, would still take you almost 4 straight days of rolling to get that all 18s set. So for you DMs out there... if a player comes to you with a character they said they rolled, and it's got six 18s, you give them a knowing wink while handing them your dice and telling them "roll again..."

Friday, September 1, 2017

Cabin In The Woods, Pt 4

I woke up early the next day in order to call the kayaking company. You see, the quality of the kayaking is heavily dependent on the river authority and how much water they release from the nearby reservoir. Strangely, the recent rains hadn't raised the river level very much, and I was worried that the river wouldn't be high enough to boat on. Luckily for us, they had released a little water, and the river was good enough (according to the proprietor).

As such, we were off for our kayaking adventure!

Day 5: Kayaking

There are *lots* of kayaking companies in the Broken Bow area. After researching, we decided to go with Yippie Kayo Kayaks. We had a good experience with them. If you're ever in the area and want to get out on the river a bit, you should definitely look them up.

There was another family in our launch, so the van was quite full on the way to the river. You might say we were crammed in there like sardines, but I'm pretty sure sardines are saltwater fish. Is there a tiny, tight-schooled freshwater fish?

Sorry, back to the actual story. We had high hopes of high adventure as we entered the river.

...except Gabriel, full of trepidation.
What a great day to kayak that was. The temperature remained in the 80s or below and the sun was occasionally obscured by clouds. The river itself wasn't very high, which was good and bad. In the area we kayaked, if the river gets too high, the rapids become... more challenging. As it was, we only had a single waterfall to go over.

Tanya was our official photographer, by the way. The following picture was taken after we all successfully made through the rapids (most of which I had to walk through, since my boat dragged the bottom) and then over the falls.

Those are the falls, under the arrow.
I had water cooler duty.

Water cooler duty
You see the cooler? It's full of bottled water. It also happens to have a small bottle of bug spray in it. It's lashed to my kayak by a single, small bungee cord. Given how I've described the river, you'd think that would be good enough to keep the cooler securely fastened. Not so much, as it turns out. There were a couple of spots where the kayak went up on its side or completely turned over (hey, it happens even on simple little turns or rocks -- for the record, I had to get out and right the kayak or move it past rocks several times).

The reason I bring this up is that even though the cooler's lid was super-tight, the cooler still got river water in it. In addition, the bug spray bottle must've leaked a little, because at the end of the trip there was a very delicious lemony smell expelled from the cooler as we opened the lid. Needless to say, no bugs wound up drinking from those water bottles...

At one point, a bald eagle put on a display for us... a display of confusion. We were paddling along when this majestic creature swooped out of a tree, diving straight towards the far bank of the river. It grabbed what looked like a rock, started ascending back towards its tree, but dropped the rock about halfway over the stream. The rock landed with a less than thrilling splash as the eagle resumed its perch.

I have no idea what I'm doing.
Our best guess is that the eagle had grabbed one of the turtles from the water near the far bank, and then either instinctively dropped it in order to crack its shell or was getting snapped severely enough by the turtle itself that the eagle decided it wasn't worth the effort. In either case, we couldn't figure out why the silly bird didn't make a grab at the fish that we could clearly see splashing around all over the river. Maybe it's a turtle-tarian?

I was surprised to learn that everyone actually enjoyed the kayaking. I had doubts about whether or not the boys would think it was fun. Photographic proof follows.

Gabriel approves of not getting sunburnt

Garrett and I try a tandem experiment. It failed.
Tanya makes me take a picture without goofy sunglasses. I smiled despite myself.
Victory! Raise your paddles for a job well done!
I've got to let you guys in on a secret. I've saved the best part of the experience for last. Are you ready?

.

.

.

SPACE PANTS!

Space Pants!
And if you're wondering, these are *not* mine, they're Tanya's, but yes, I absolutely want a pair.

This was the last of our adventures on the surprise summer vacacay. It was unexpectedly enjoyable. If you ever have a hankering to rent a Cabin In The Woods, indulge that hankering. And get out on some zip lines, and onto the river in some kayaks. If you can avoid or embrace the thunderstorms, you're bound to have a grand ol' time!


Wednesday, August 30, 2017

Cabin In The Woods, Pt 3

After a day full of fun, we figured that Day 4 would wind up being a chill day. The rain helped dampen (see what I did there?) any ideas of outdoor activities. Chill day was ON!

Day 4: Roku To The Rescue

We actually managed to sleep in, which is a particular achievement for me. We didn't roll out of bed until 9:00! After breakfast, we set up the Roku and figured out what our viewing schedule would be. First up was Last Week Tonight, which we all enjoy.

Weekly, 30 minutes, MUST SEE TV!
If you don't make a habit of watching Last Week Tonight with John Oliver, you should. Even if you decide not to watch it on HBO, you can see the main stories on their YouTube channel.

After a little TV, we did individual activities. For me, that included reading and drawing. And no, I'm not going to post any of the drawings. They're just sketches and not all that great. Maybe, at some point, I'll post a couple. Trust me when I tell you that they're nothing special at this point... :-)

After lunch, it was time for another board game. This one was Roll For The Galaxy.

Colonize the Galaxy!
This is another of our staples. It's pretty easy to pick up, and easy to convince everyone to play. It's one of the few games that actually takes as long as the box says it should. These games are typically pretty competitive as well, but it usually turns out that Garrett or Gabriel wins. This time, Garrett claimed the mantle of Conqueror of the Galaxy. Gabriel came in second, again. Actually, he and I tied, I think, which is a pretty solid showing for me.

You'll notice that Tanya did *NOT* win this one. I wonder if she was still hung over from the Catan win...?

A little downtime followed, then we fired up the Roku again and watched My Hero Academia.

Anime with angst! That might be a redundant description.
This is another show that we watch regularly. We are typically behind in watching it, because we (Tanya and I) like to wait for the voice actors to dub the episode instead of reading the subtitled version on release. The boys have absolutely no problem reading the subtitles. In fact, I'm pretty sure Gabriel has read at least part of the manga as well.

Finally, dinner time rolled around. As I mentioned the the last post, we went back to the Blue Rooster. I ordered the same main course as the previous night, but we skipped the fried pickle slices this time. I had to save space for the fried pie for dessert while remaining at least somewhat comfortable in my pants.

Our final entertainment for the evening was delivered through a viewing of Ghost in the Shell.

2.0, because adding a little CGI warrants a new version
Tanya, as it turns out, had never seen the original. The boys had seen parts of it, but not the whole thing. If you have only seen the live-action version from earlier this year, you should make time to see this one as well. It's a different story than that told in the new one, and quite a bit more cerebral, in my opinion.

After the movie was over, we went over the plan for the next day (which was to get out of the cabin and go KAYAKING!). Grumblings were heard and summarily ignored.

What happened next will BLOW YOUR MIND! Wait, I just said it was kayaking. I guess it won't blow your mind all that much after all... ;-)


Tuesday, August 29, 2017

Cabin In The Woods, Pt 2

So... who won the Catan game? What happened on days 3 and 4 (and 5 and 6, for that matter)? WHY IN THE WORLD WOULD YOU LEAVE US IN SUSPENSE LIKE THAT, RUSTY?!

Sorry about that. I'm trying to pace myself. Gotta keep the post count up somehow... 

On to Day 3!

Day 3: Zip-lining... or Thunderstorms, and Catan pt 2

Our planned activity for Day 3 was zip-lining. Unfortunately, Mother Nature made other plans. We were scheduled to go before mid-morning, but we woke up to thunderstorms. I called the zip-lining company, and they had decided to not even send crews out to check the lines and that all morning sessions were cancelled. We were bummed, but then remembered that we had a game of Catan waiting for us!

Do you want Wood for your Sheep?

We got back to the game. Tanya was in the lead with Gabriel a close second. Garrett was third, owning all of the favorable exchange ports. I, as usual, was bringing up last place pretty solidly. For some reason, I always pick a pretty common number, and then we never roll it throughout the game. I think that 9 was my nemesis this time...

We finished by lunchtime, with the final standings as they were the night before: Tanya was crowned Lady of Catan, with Gabriel as the next largest land holder. Garrett had the largest army, and I had the biggest wheelbarrow of nothing you've ever set eyes on. Truly, it was magnificent to behold how much nothing I brought to that game... 

The good news is that the rain had cleared off enough to consider the zip-line again. I called the place, and they were indeed open and had a spot for the four of us. We went up there after lunch for zip-lining greatness!

The adventure was courtesy of Rugaru Adventures, and the guides were all fun. We went with another family of three and a single adventurer, so our party was decently sized.
Proof we all went outside!
The course had six zip lines to go through, and we kept a brisk pace (as the weather was still somewhat threatening). I had never been zip-lining in any form or fashion, although everyone else had. Noob!

I think it's safe to say that the entire group enjoyed the adventure. Some of the views from the lines were pretty impressive, especially the one that takes you out over the lake. Oh, you say you'd like a picture of that? Don't worry -- Rusty will provide!

Does the line dump you into the lake?!
And yes, Tanya smiled the whole time. I think she was still glowing from the recent conquest of Catan.

Not to be outdone, Gabriel got a wave in to the camera while on one of the lines.

I'm zipping away! Bubye!
Even Garrett enjoyed himself. He typically doesn't smile for pictures, but I don't think he could help himself.

That's not a smile, Dad -- it's a smirk!
But honestly, do any of you think I would not claim the silliest picture pose? Hey, I may not be very good at board games, but I know how to ham!

Winky!
And then there's the group pose.

We could take a serious picture, but why?!
I'm really glad we got the chance to do this. The operation is well-run, fun, and definitely worth doing if you're ever in the area.

All that zipping around left us hungry. We decided to abandon all pretense of finding food that was somewhat good for us and went to The Blue Rooster.

There's also a blue metallic rooster in the yard.
The Blue Rooster specializes in fried food. This is where the wheels came completely off of my vacation sensible eating plan. We loved this place. We loved it so much, we went back again the next night. So much tasty-fried goodness! They even had fried pies for dessert! The first night, I had the lemon fried pie. The second night, it was apple (of course).

We were pretty lethargic by the time we got back to the cabin, so we settled in for a long winter's nap. Only, it was summer. And it wasn't a nap -- we just laid around chatting and reading until we started to fall asleep, then went to bed. See? I suck at poetry because I'm too literal... ;-)

Stay tuned for Day 4!

Monday, August 28, 2017

Cabin In The Woods, Pt 1

Cabin In The Woods!
Or, short summer vacacay, if you prefer. Originally, we had opted NOT to have a summer vacacay since the boys were going on a cruise with their mom and extended family, and I've got a longer trip to Hawaii in September. However, we just couldn't resist the siren call of the Oklahoma woods, so we booked a cabin and left on a Friday to spend a few days "roughing it" in the far reaches of Broken Bow in southeastern Oklahoma.

Day 1: Travel, Arrival, Dinner

The drive from DFW to Broken Bow was shorter and nicer than I expected it to be. I'd driven to Broken Bow once before, years ago, in the days pre-dating Google Maps. It took close to five hours that time, but this time the drive was right around three hours -- perfect for a weekend jaunt. It also gave me an excuse to play my favorite travelling music: "There Came An Echo," by Big Giant Circles. You should definitely check out ALL of his stuff -- it's all well worth the listen and subsequent purchase!

We made it to the cabin and settled in. After milling about for a bit, we decided to try to find somewhere to eat. A lot of vacacay is about eating, after all. The first place we tried was Rolling Fork.



This place is simply fantastic. They serve natural artisan foods... in the middle of Hochatown, Oklahoma. I can't describe how pleasantly surprised I was that Tanya found this place. We enjoyed it so much that we wound up going back again the next day to pick up a lunch to go.

The first day ended with relaxing at the home-away-from-home. We made sure all the electronics worked, entertained ourselves, and made an early evening of it. We had an active day planned on the 'morrow.



Day 2: Four-mile Walk, Catan pt 1

The day began with us hiking in Hochatown State Park. Tanya and I wound up making this trek alone, since both boys and "accidentally" stayed up really late and didn't feel up to walking through nature with us.

Trees!

The walk was really pleasant. There was some rain in the forecast, but it held off while we walked. The clouds kept the heat index down a little too, which was not quite refreshing. The humidity, after all, made us feel like damp washcloths pretty quickly.

I did manage to make a friend on the trail. Millipedes were all over the place. We first passed a dead one on the trail about five minutes in, and I saw about a half dozen more during our walk. This one, though... we were buddies. I called him Miles the Millipede. He didn't seem to mind.

Promises to keep, and miles to go...

Strangely enough, I managed to get flea-bitten on the ankles, even though I was wearing long socks, pants, AND bug spray. Apparently I didn't spray my ankles adequately. Perhaps I've learned my lesson... but don't count on it. Fleas gotta eat too!

Dinner on Day 2 was at The Moon Tower Bar and Grill. This was another place I liked very well, and the only restaurant we went to in the direction AWAY from Broken Bow (and towards Arkansas).

So *that's* what a moon tower looks like...

This was one of those kinds of places that had an eating challenge. I can't remember what exactly it was... a 48 or 60 ounce steak of some sort. It sounded painful, and I didn't try to find any wall of champions. Still, our food was good, and I enjoyed the ambiance. It reminded me of... well, most of the bars and grills from around where I grew up in central Texas.

The final activity of the day was cracking open Settlers of Catan. This is a board game that we tend to play at least once a summer. This year, we added the Cities and Knights expansion, which made the game significantly longer for us. So long, in fact, that we had to pause the game and return to it the next day.

More on that in the next post!