星之一角

What have you found for these years?

2016-01-23

第三小鎮 Design Town (Flip City)

第三小鎮 Design Town (Flip City)
基本上就是 Dominion-like 的遊戲 XD

我其實並不喜歡 Dominion, 不過倒是還算頗喜歡 deck-building.
目前我給的分數是 8/10, 比 Dominion 高一分,跟 San Juan (聖胡安)
同分,比 Race for the Galaxy 少一分。清單在這:
User: godfat: Board Game Collection

當然這不是嚴謹的評分,只是我個人玩過的 boardgame 記錄而已,
也理所當然反映了我個人的偏好,沒有特殊意義。(也可能有我漏沒記錄到的,
能提醒我一下會很感謝 XD)

說到 deck-building, 強力推薦 War of Omens, 雖然不是 boardgame,
也不全然是 deck-building, 他是必須先組自己的銀行,然後再在遊戲中
deck-building. 遊戲規則也不適合做成 boardgame, 計算太過瑣碎。
雖然暫時停止開發了,但整個機制非常有趣,也有很多發展空間。真的很可惜...



回主題,我覺得第三小鎮設計得相當不錯,原則上我覺得沒有太多改善的空間。
硬是想了想,我覺得由於遊戲後期的變化性不夠大,或是說計算變得瑣碎,
玩起來比較沒有快感,反而會覺得有點煩悶,想趕快結束並進行下一場。

針對這點,我想有兩種改善的方式。一個是縮短遊戲時間或是增加遊戲節奏,
另一個則是讓遊戲本身有更多的變化。

縮短遊戲時間:

一個最簡單的方式就是把獲勝分數從八分改到六分,並把便利商店的出牌獲勝
條件依比例降至十三張獲勝。我目前還沒實際嘗試過大量使用購物中心,不過
獲勝分數降至六分的話,應該比較容易藉由「賭一把」使得購物中心的那一分有
更大的影響力。

當然,這樣或許降低了技術成分,增加了運氣成分,一般我是不樂見這種狀況。
不過我覺得要不要賭一把確實也是這個遊戲中非常有趣的一部分。賭不賭隨人!
大概是這種感覺。

另一個縮短遊戲時間的方向是在建設時期可以同時購買和升級。我不確定這樣
其他牌是否會需要調整,不過這樣應該可以讓遊戲節奏加速非常多,畢竟可以
同時購買便利商店又升級住宅,或許標準打法就會變成這樣吧。但如果出現
標準打法,也等於是遊戲變化下降了。

增加遊戲變化:

我目前想到有兩種可能,一個是每回合都可以選擇「留下」一個建築在場上。
下一回合時,依照留下來的順序依序執行,執行完畢才開始出牌階段。或許也可以
在建設階段增加拆除建設的選項。

當然,這樣意味著遊戲節奏會變快很多,因此獲勝條件必須相對提高,可能要改成
兩倍以上,變成要十六分獲勝或是三十張牌在場上之類的。

這樣的好處我想有兩個,一個是主題上也比較有建設的感覺在,不然每次都清空
說實在我覺得也頗怪的。當然我不是個很在意主題的人,這對我來說比較可有可無。
另一個則是增加一些策略性的成分。牌可能也要因此調整就是了,畢竟這改變很大。

另一個是可以「強制購買」別人棄牌堆的牌。這樣一個很重要的好處我想是增加了
玩家跟玩家間的互動性。不然以目前的規則中,玩家順序甚至沒什麼差別...。
通常沒什麼互動的遊戲,最少最少玩家順序也是有不少影響力的。

大概是這樣。

我想買擴充!!

不過對於這個露營區有點意見。我不是很喜歡這種增加記憶負擔的卡片 :(
然後我還滿喜歡交流道的設計。多多利用棄牌推我覺得挺好的。反過來說,
其實棄牌堆才是真正的手牌 :P


附註一提,原先我有些擔憂的兩面設計,不小心看到我覺得不成問題,基本上
不太會不小心看到。比較麻煩的是有時候洗牌或是拿牌在手上甩(等待其他玩家)
會不小心把其中幾張牌翻了過來,然後忘記原本到底是哪一面。不過這可能
只是習慣問題,以後可能就不會不小心了。目前我覺得兩面的設計還是好處多於
壞處。不過當然,如果有什麼機制可以解決「不確定這張卡現在應該是哪一面」
會更好。

另一個是原本覺得哭臉跟醫院的計算很麻煩。不過現在習慣了後又覺得不難算了。

2016-01-19

A few thoughts on "nil Is Not NULL, and Other Tales"

A few thoughts on: nil Is Not NULL, and Other Tales.

nil is an Object, NULL is a memory pointer
[...]
To be absolutely clear, a segmentation fault and a runtime exception are radically different things. But the consequence, your program aborts, makes them seem quite similar.
Yes, I agree. However:
and if its "nil" doesn't support that, something must be done. This characteristic of a statically-typed language makes nil seem dangerous.
No, it's not. It's called NullPointerException in Java, it's still just an exception. This is not the characteristic of a statically-typed language. They could be the same in both statically/dynamically typed language. My point is that nils are not superior in a dynamically typed language.

nil is mathematically realistic
[...]
A value like nil signals that "no mapping is available for that input". It's a very useful concept.
The concept is useful but are we talking about the concept or nil in Ruby in particular? You're talking about null set here but it's not the nil in Ruby. The nil in Ruby represents "nothing" not "null set".

nil is mistreated in Ruby
[...]
In the first case, developers tend to see nil as an error, and hence, it is quite unwelcomed. "Oh look, that method returned a nil, something must be wrong!"

No, not at all! Nothing need be wrong. The method returned a nil to say, "no value here!"
This really depends on the API. If an API claimed that it should never return nil, then it should never return nil and if nil was returned, surely something must be wrong! On the other hand, of course we could design an API which could potentially return nil. In Haskell, this would be called Maybe. A value of Maybe would either be Nothing (nil in Ruby) or Just something else. In this case, indeed nothing need to be wrong. It's all depending on the specification. The question is, could the specification really enforce the requirements/constraints?
In Rubinius, this is such a problem that we had to introduce a special value we called "undefined" to be able to implement the Ruby core library in Ruby. The problem is that some methods take nil as a value, but also have a default value. So, we were unable to distinguish between some_method() and some_method(nil).
Indeed this is really annoying. The concept of undefined was there but Ruby doesn't have a value for it. I often wrote Undefined = Object.new for default arguments. I hate that JavaScript has null and undefined, but seriously sometimes we do want "undefined" in Ruby. Hash is another example which has this difference.
h = {}
h[0] = nil
h[0] # => nil
h[1] # => nil
h.has_key?(0) # => true
h.has_key?(1) # => false
h.keys # => [0]
h.values # => [nil]

The "lonely operator" is an unnecessary mistake
The "lonely operator" supposedly solves the problem of calling a method on nil that then raises a runtime exception causing the program to abort.

Unfortunately, it only partially solves this problem
I totally agree that this is a mistake and it does not partially solve the problem, because it does not solve the problem at all. It's merely making it easier for us to write sloppy codes which could hinder real bugs, encouraging the use of unstructured data (i.e. hash tables) over the places, spreading nils around the world.

It's somehow a curse, from the `try` method from Rails, from people abusing JSON and hash tables, using them like JavaScript objects without classes.

It's backward.

Not to mention a special syntax for it. Ruby's syntax is already horribly complex.

nil is A Good Thing™
Well, I can't say it's a good thing or bad thing. We need the concept, but not necessarily the current nil. The problem is that, there's no way to enforce an API that would never return nil. Granted, actually this is the same issue lacking static types. It's just that nil is the most possible value which could sneak in because THERE ARE SO MANY METHODS could return nil. If we made that most of the API, the objects and methods from standard library would seldom return nil, then we are probably saved.

For example, h[0] could give me HashMissingValue instead of nil, and other methods could return other similar values, and the point is, they should be distinguishable.

Yes, and that's actually very similar to that Traceable nils in Rubinius which mentioned in the bottom of the post. That, yes, could probably solve the issue.

The simple alternative to the "lonely operator"
Defining method_missing on nil can't be the alternative to that lonely operator, unless we're using "refinements" to localize the changes. I am not saying refinements are good, but I think we all agreed that global behaviour modification is 99% bad, unless we're talking about a small script.

Ruby developers need to see where nil is
[...]
This problem of knowing where a value comes from is much bigger than nil. It is a result of the fundamental tradeoff that a late-bound language (usually called a dynamically-typed language) makes relative to an eagerly-bound language (usually called a statically-typed language).
Yes, exactly, though even a statically typed language could still be plagued by nil. See NullPointerException again. Some talked about Option type (again, Maybe in Haskell) could be the answer, for example Scala does return this for some of the methods. However, I don't feel this solve all the problems because there are still nulls somewhere else. Guess what, Option value could also be null. So actually there are 3 possible values: Some something, None, and our beloved null.

Well.
Late binding provides a malleable system that easily manages the complexity of high-uncertainty contexts. Objects can interact with other objects that provide certain behaviors. They do not have to be specific kinds of objects. The lessening of the constraints that the developer's assumptions impose on the system can increase the utility and resilience of the system.
This is certainly true though. While now I strongly believe in static typing much more, this is the reason why I still cannot give up Ruby and still prefer Ruby in some cases. Playing around it, interact with it. That's sometimes much more pleasant, until, I need to scale the complexity...

Traceable nils in Rubinius
[...]
In the past, we have only ever used that precise value. In other words, all the other bits are zero. But nothing requires this, and those other bits don't need to be wasted. On 64bit architectures, this gives Rubinius approximately 259 values of "nil". That's more than enough for a typical Rails app, I'm sure.
I was like, what the hell was this? when I read this paragraph. But to think about it, indeed we could use this trick to provide insights about where the nil was generated from. I highly hope this would work well and debugging nils could be much easier, and then, perhaps we could really afford returning nil everywhere. I don't know, but maybe.

Cheers,

All texts are licensed under CC Attribution 3.0