Wednesday, July 25, 2012

Get a peek at the unidentified items in Diablo 3

It has been almost 3 weeks before the trick was revealed, and Blizzard has, so far, done nothing to address this issue. Not that they did not have the resources. There were two major issues (Wizard & Barbarian being invincible) that were quickly nerfed within 24 hours, but Blizzard just does not care about the standard gaming experience, at least not their top priority; at least that's how they made me feel.

The item rolling is so random that I usually like to sell the items as unidentified rather than identifying them myself, but this bug completely destroyed the whole unidentified item market.

Let me, first, explain how the trick works.

1. Go to Auction House and open the inventory window.
2. Press ENTER to bring out the dialog prompt.
3. SHIFT-left click on the unidentified item
4. Enter two multibyte characters (Chinese, Japanese or just two Unicode symbols)
5. SHIFT-left click on the unidentified item again.
6. You prompt should look like: [Item]●●[Item] (● can be any multibyte characters)
7. Now, left-click in the middle of the ●● characters.



8. Press DELETE 3 times
9. Now, the internal code of the unidentified item is revealed.




Now, the string [Ring] Item:2,1146967347:935114366:1289779934,1599105366,-1976254572,-244372676:-1:0:130760:15:3:8:390:390:0:0:6:0:873858439:|h[Ring]|h may seem meaningless to you, but in fact that's all the information you need to figure out what the item is.

You can copy the string and paste it to a Diablo 3 Item Identification Tool (http://www.mynikko.com/d3/) to find out what the affixes are.

Fix it, please, Blizzard. It's only one if-statement.

Wednesday, July 4, 2012

You don't need RMAH to finish Diablo 3

I have read through most of reviews, both positive and negative, of Diablo 3. I must clarify one thing: you do not need to spend real money in order to finish the game (including Inferno level).

After 400 hours into this game, I did not spend a single extra penny. In fact, I added more than US$100 into my Blizzard account for future game purchases by selling items in RMAH.

Many people are complaining they cannot get the items they want, but that's how Auction House comes in handy. You got some items you do not want; you sell them at Auction House in exchange for buying something you want from there.

People are complaining the items they want are expensive, but your items can be sold at that price level, too. Blizzard cannot just give you great items; you have to hunt for them.

My character is capable of beating the Inferno level now, but I choose not too. I chose to farm items. Yes, its a repetitive process, but it has always been a major part of Diablo series.

As 1.0.3, all monsters at Inferno level have the possibility of dropping iLv61~63 items (just at different drop rates). One iLv62 rare (yellow) ring with good attributes can be sold for 20 millions or more of gold (or US$40+ in RMAH) if you hit the jackpot (e.g. IAS + Cri. DMG + Cri. % + Life on Hit). A good iLv63 weapon are even more expensive, I have seen weapons that are being sold for more than 100 million. I did not have such luck, but I did manage to get a couple rings that were sold for 5 million each and some for US$20 each in RMAH. With those money, I greatly improved my gears to a level that I can now make about 5 millions in a few hours by selling items. Even un-identified iLv62 rings can be sold for 1 million on the public trading channel. I get those rings everyday (at least one per day). The more those Chinese gold farmers/bots jack up the market, the better price you items will be sold.

I have to say the current Diablo 3 game system is flawed, but it would not be fair to say something like this game sucks because Blizzard forced gamers to spend money in RMAH in order to finish the game. If you do not want to spend time farming, then Diablo series is not for you in the first place. RMAH provides a short cut for people who have little time but are willing to pay the price. For most players, just listen for the drop sound that will change your gears/game entirely. Again, you do not need to spend more money if you do not want to.

Now, Blizzard is publicly announcing that they are thinking about changing the Magic Find (MF) mechanism so fast MF gear switching during combat will not be feasible. Again, this is why I mentioned in the previous review that Blizzard always tries to control the players so they play the way Blizzard wanted. While fast MF gear switching might seem unfair for melee classes, Blizzard could have introduced something that encourages players not to switch their gear during combat (e.g. if you don't switch your gears, there is a possibility that a goblin will pop out after the combat). Why does Blizzard always try to limit the players' playing style while there are more important things to do, like stopping those bots, or at least make them disappear from the public channel. Yes, there are bots, but at least don't let them remind me through public channels that it is totally stupid to farm because 1 million gold can be bought for less than US$2. What about legendary upgrades? How about make multi-player experience more enjoyable (right now, no one wants to play multi-player games)? How about some positive changes for the gaming experience? Encourage us instead of limiting/nerfing.

Blizzard, C'mon. You can do better than this.

PS. the above review is based on Patch 1.0.3b

Wednesday, June 27, 2012

Is Diablo 3 Another C&C4?

I know Diablo 3 and Command & Conquer 4 are two completely different games (even genres), but take a look at C&C4's reviews and you will find that both share the same characteristic: sequel of classic series got ruined by capitalist business giants (Blizzard/Activation and Westwood/EA). I am not saying D3 is dead but Blizzard should really listen and respect their customers.

First things first, I would rate this game around 7 out of 10 if this was not Diablo 3. The graphic, the music, voice acting and the design make it a decent game. However, I cannot believe this is a final product from the company that made the same D1 and D2. I would elaborate this later. I give it a 5/10 for being D3.

I have to admit that persistent internet connection requirement is sometimes unavoidable (e.g. MMORPG), but completely removing single player mode from D3? To me that is not acceptable at all. Players will still want to play on Battle.net eventually, so piracy prevention is not an excuse. Even StarCraft2 which is focused on online PvP has single player mode. One of the main reasons why I love single player mode is that I can change the game save files to experiment with different gears that is almost impossible for me to get online and test out what gears are best for my characters. They made the whole game completely Blizzard service dependent. I do not like the trend that games are no longer yours. Let's rate D2 and D3 hundred years from now. I will be able to play D2 even after years, but D3 is just a worthless game client without Battle.net of Blizzard. For this reason, I give this game 2/10 (No, 4 people in the same room does not count as MMORPG).

Now, I will explain why D3 game system is fundamentally flawed. RPG is about character development and gear collection. D3 completely neglected the first part. What so unique about your character in D3 are your name, class and gender. Every level 60 character of the same class is virtually the same without gears. The stat points are added for you automatically. The worse of all, the gears play too much role in the whole system. You do not feel your character is developing and growing. You level up simply because you want to meet the item level requirement. Why is this? Every time you level up, you get 1~3 stat point toward different categories (automatically added), depending on your character class, but one item that adds 100 strength and 100 vitality, which is common by the way, just makes your character looks like a fool. One piece of common item is almost 50 times more effective than leveling your characters.

DPS also played too much role. For example, a weapon with 1000DPS deals more damage than a 700DPS weapon that adds 150~200 points to main stat of your character. The DPS itself is more important than the stat, and the item stat is more important than your character. Your character becomes a meaningless skeleton that merely holds your gears together. The brainless DPS system also decreases the fun factor. The elemental nature of the weapons is almost meaningless, because weapons all deal the same damage regardless the nature of your enemy. They do have their differences, like cold can slow and poison has damage over time...etc, but I do not understand why Blizzard implemented the elemental system but decided to simplify it, especially when it was proven to be successful in D2.

Now, everyone is criticizing the Inferno level, but I actually like the design. The only mistake Blizzard made was to make it obvious so players think that they have to beat the Inferno level in order to "finish" the game. If inferno level can only be access through a secret portal, for example, Leah's bed after you finished the Hell difficulty, no one will complain as much. Inferno is like a challenge, for hardcore players to get great items, but not for average players to explore. Like Whimsyshire, no one would complain if the flowers are too strong, because it is a bonus level. In fact, not many players understand that you have to build up your all resistance to a certain point in order to "steal" items from those mobs. I do have to admit that Inferno was broken for melee class, but it was pretty OK for ranged class.

What made Inferno such a beast is, in fact, the fundamental flaw I mentioned earlier: this game is too gear oriented. If the stat of your characters plays about 75% of your overall damage/defense while the gear makes up the rest 25%. Inferno will be much more playable for players without gears. Now, the game design plus the difficulty of Inferno force players to spend gold in auction house. I do not know if this was an intentional design or not. If this was intended for making a profit, then Blizzard will see the profit goes way down because players are not that stupid, Mr. Obvious.

Those are just game design issues that can be addressed in future patches, although I do not know how Blizzard is going to be able to patch the gear oriented design. What disgusts me the most is the attitude of Blizzard: Blizzard created the game and wanted players to play the exactly way they wanted. I do have to admit that some of the nerfed skills are overpowered, but what about those underused skills? They nerfed some of the popular skills, but they did not think the reason behind it: why players do not choose other skills? They do not because those skills sucked. Period. The shameless person who said D3 does not need customize stat build because it got countless skill combination should be working for tobacco marketing companies.

1.0.3 is an arrogant display of Blizzard; they force you to play this game exactly they wish you to play. Yes, there are some positive changes (at least melee class can access Inferno Act3~4), but the rush changes clearly showed that they do not care about player experience. For example, they changed the drop rate and magic find for chests, and now they are thinking about changing it back. People are being told what you need to be doing in school/at work, and they do not like the same experience in game. This clearly showed that there is something wrong with Blizzard's QA department.

It is extremely easy for Blizzard to test out if the gears have the potential to be overpowered by giving QA testers the best gear within the game design BEFORE the game release. The players are not QA, and players should not be the victims of consequence of those irresponsible patch changes. As a game designer myself though, I think Blizzard needs to fire some of the management directors (or just fire one, the rest will learn). This is clearly a management/direction issue. They are responsible for those irresponsible changes. If Blizzard think twice, they could have buff some of the underused skills and classes instead of nerfing the difficulty. I do not know about others but I found the game much more boring because there is nothing left for me to do now.

It is ironic that I typed so much for a game that I dislike so much. No, it is not. I like this game; I want D3 to be another classic. I just hope people in Blizzard have the same motivation and desire to do so.

P.S. The above review is based on Patch 1.0.3a.

Monday, June 25, 2012

The annoying templar, Kormac (Diablo 3)

It's funny that many players complained about how annoying those followers are in the official Blizzard forum. I actually liked a lot of their dialogues. However, I could not find a complete list of D3 follower quotes online.


I did find this funny comic, which I did a (nice?) little translation.




Wednesday, March 21, 2012

Easiest Way to Disable Google Chrome Auto Update


Any program trying to be smart is stupid. Google Chrome is one of them. Its aggressive automatic update mechanism just makes me sick (same as Adobe family). For me, any ”automatic” action without my consent is considered offensive viral behavior. So I used the same method against Google Chrome.






First, remove any Scheduled Tasks placed by Google Chrome which can be found in the control panel.

Second, rename the auto-update program.

Let’s use the god damned Google Chrome as our example.

For Windows XP, go to the following directory (if you cannot find the ‘Local Settings’ directory, you need to enable the show hidden file option):

C:\Documents and Settings\[User Name]\Local Settings\Application Data\Google\Update\


Rename GoogleUpdate.exe to something like GoogleUpdate.GoToHell.

You can also delete it if you want, but let’s just save it just in case you need to update the software later.

Third, the most important part of the while operation: make a directory named “GoogleUpdate.exe

This way, Google Chrome will not be able to create the file named GoogleUpdate.exe. Thus, prevent it from trying to enable the update itself.

In short, the above operations in terms of DOS commands are:
C:\>CD "C:\Documents and Settings\[User Name]\Local Settings\Application Data\Google\Update"

C:\Documents and Settings\[User Name]\Local Settings\Application Data\Google\Update\> ren GoogleUpdate.exe GoogleUpdate.GoToHell

C:\Documents and Settings\[User Name]\Local Settings\Application Data\Google\Update\> mkdir "GoogleUpdate.exe"


That’s it. To revert the whole process, simply remove the “GoogleUpdate.exe” directory and rename “GoogleUpdate.GoTOHell” back to “GoogleUpdate.exe”

Easy enough right? You can use the same trick for those auto-update-maniac programs including, but not limited to, Adobe Photoshop, Acrobat Reader…etc. Some programs, like Adobe malware, even place start up processes which runs automatically every time your computer starts. You might want to remove them from the autostart list by cleaning the autostart folder and msconfig.exe (in Windows case).

Tuesday, March 13, 2012

Auto-increment ID Obfuscation

One problem I encountered is that an auto incremented ID may expose certain information that you do not want your clients to know.

For example, http://www.company.com/order?id=1234 tells you that this company probably does not have a lot of new orders since your order probably is the 1234th of their overall orders. http://www.NewDatingSite.com/member?id=256 is simply telling people that you probably will not be able to find lots new matches since the newest member is just their 256th member.

Of course you can encrypt the ID number to make it more complicated like http://www.ConfusingID.com/stuff?id=!W%23R%5E%25YFT%5E. While this ensures that your customers probably will not be able to probe around and know that they are actually your first ever guinea pig customer, they will definitely have a fun time reading that ID to your service representative when calling over the phone. That ID is simply too ugly for the eyes.

You can also create a 1-to-1 hash table (beware of the collisions) or use some mathematical skills to create a mapping algorithm, but that is just too complicated for me.

I will just present the approach I am currently using. One of the main ingredients is base32 encode. Base32 encode has one major advantage over Base64 encode, that is: base32 is URL ready; it does not require additional encoding for URL while Base64 uses '=' character, which will need to be URL encoded as '%3D'.

Let's just see the two main functions:
function id_encode($id) {
return base_convert((9999999999 - (float) $id) , 10 , 32 );
}

function id_decode($fakeid) {
return 9999999999 - (float) base_convert($fakeid, 32, 10);
}


Let's use some numbers to run the following code:
<?
printf("%s → %s → %s <br />", $test, id_encode($test), id_decode(id_encode($test)) );
?>


The output would be:
1 → ghq6n2 → 1 
2 → ghq6n1 → 2
3 → ghq6n0 → 3
100 → ghq6jv → 100
1000 → ghq5nr → 1000
10000 → ghpsuj → 10000
1000000 → ggrm53 → 1000000
94256245 → dntnje → 94256245


So instead of having http://www.mycompany.com/order?id=3, the new URL will be: http://www.mycompany.com/order?id=ghq6n0. Yes, the ID is longer, but the length is fixed. One of the reasons why we need a fixed length ID is that user will have no way to tell the relative position of the ID in the whole database.If you do not need to have fixed length, just remove the minus 9999999999 part, whose purpose is just for fixed length padding.

It is pretty simple right? If you don't need encryption, you can simply stop reading right here.



Now, some people might need some simple encryption. Let's throw in xor and base32_encode (base32_encode is needed because string after xor might not be a printable char). Of course, if you intentionally choose your xor key, you can even make the ID resemble a meaningful string (but will gradually obfuscate as the number grows larger and reveal the fact that the number is growing). The following is an example with xor encryption.

1 → mycompanynbq → 1
2 → mycompanynba → 2
3 → mycompanyncq → 3
100 → mycompanyzca → 100
1000 → mycompanqvma → 1000
10000 → mycompaeqjia → 10000
1000000 → mzokais22faa → 1000000
94256245 → mzjoaic3yzlq → 94256245




Another encrypted example without padding:
1 → ny → 1
2 → nu → 2
3 → nq → 3
100 → nriq → 100
1000 → ffoq → 1000
10000 → myflc → 10000
1000000 → fibl6yq → 1000000
94256245 → nuk2kncr3e → 94256245



Now let's examine the xor_this function, it's also pretty short (and it's actually an example from php.net):

<?php
function xor_this($string) {
$key = 'JohnyBeGood';

$text = sprintf('%s', $string);

$outText = '';

for($i=0;$i<strlen($text);) {
for($j=0;$j<strlen($key);$j++,$i++) {
$outText .= $text{$i} ^ $key{$j};
}
}
return $outText;
}
?>


Finally you need the base32_encode and base32_decode functions. Interestingly, PHP offers base64 encode/decode, but not base32. You can Google a bit and find it right around here: http://xref.moodle.org/nav.html?lib/base32.php.source.html

For those who are too lazy to click (or the above link is down for some reason), I will just paste everything here:
<?php
//
// +----------------------------------------------------------------------+
// | Base32 Library |
// +----------------------------------------------------------------------+
// | Copyright (c) 2001 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is dual-licensed. It is available under the terms |
// | of the GNU GPL v2.0 and under the terms of the PHP license version |
// | 2.02, available at through the world-wide-web at |
// | available at through the world-wide-web at |
// | http://www.php.net/license/2_02.txt. |
// +----------------------------------------------------------------------+
// | Minor fixes and additional functions by Allan Hansen. |
// | Moodle porting work by Martin Langhoff |
// +----------------------------------------------------------------------+
// | base32.php - based on race.php - RACE encode and decode strings. |
// +----------------------------------------------------------------------+
// | Authors: Allan Hansen <All@nHansen.dk> |
// | Arjan Wekking <a.wekking@synantics.nl> |
// | Martin Langhoff <martin@catalyst.net.nz> |
// +----------------------------------------------------------------------+
//

/**
* Base32 encode a binary string
*
* @param $inString Binary string to base32 encode
*
* @return $outString Base32 encoded $inString
*
* @access private
*
*/

function base32_encode($inString) {
$outString = "";
$compBits = "";
$BASE32_TABLE = array('00000' => 0x61, '00001' => 0x62, '00010' => 0x63, '00011' => 0x64, '00100' => 0x65, '00101' => 0x66, '00110' => 0x67, '00111' => 0x68, '01000' => 0x69, '01001' => 0x6a, '01010' => 0x6b, '01011' => 0x6c, '01100' => 0x6d, '01101' => 0x6e, '01110' => 0x6f, '01111' => 0x70, '10000' => 0x71, '10001' => 0x72, '10010' => 0x73, '10011' => 0x74, '10100' => 0x75, '10101' => 0x76, '10110' => 0x77, '10111' => 0x78, '11000' => 0x79, '11001' => 0x7a, '11010' => 0x32, '11011' => 0x33, '11100' => 0x34, '11101' => 0x35, '11110' => 0x36, '11111' => 0x37);

/* Turn the compressed string into a string that represents the bits as 0 and 1. */
for ($i = 0; $i < strlen($inString); $i++) {
$compBits .= str_pad(decbin(ord(substr($inString,$i,1))), 8, '0', STR_PAD_LEFT);
}

/* Pad the value with enough 0's to make it a multiple of 5 */
if((strlen($compBits) % 5) != 0) {
$compBits = str_pad($compBits, strlen($compBits)+(5-(strlen($compBits)%5)), '0', STR_PAD_RIGHT);
}

/* Create an array by chunking it every 5 chars */
$fiveBitsArray = split("\n",rtrim(chunk_split($compBits, 5, "\n")));

/* Look-up each chunk and add it to $outstring */
foreach($fiveBitsArray as $fiveBitsString) {
$outString .= chr($BASE32_TABLE[$fiveBitsString]);
}

return $outString;
}

function Base32_decode($inString) {
/* declaration */
$inputCheck = null;
$deCompBits = null;

$BASE32_TABLE = array(0x61 => '00000', 0x62 => '00001', 0x63 => '00010', 0x64 => '00011', 0x65 => '00100', 0x66 => '00101', 0x67 => '00110', 0x68 => '00111', 0x69 => '01000', 0x6a => '01001', 0x6b => '01010', 0x6c => '01011', 0x6d => '01100', 0x6e => '01101', 0x6f => '01110', 0x70 => '01111', 0x71 => '10000', 0x72 => '10001', 0x73 => '10010', 0x74 => '10011', 0x75 => '10100', 0x76 => '10101', 0x77 => '10110', 0x78 => '10111', 0x79 => '11000', 0x7a => '11001', 0x32 => '11010', 0x33 => '11011', 0x34 => '11100', 0x35 => '11101', 0x36 => '11110', 0x37 => '11111');

/* Step 1 */
$inputCheck = strlen($inString) % 8;
if(($inputCheck == 1)||($inputCheck == 3)||($inputCheck == 6)) {
trigger_error('input to Base32Decode was a bad mod length: '.$inputCheck);
return false;
}

/* $deCompBits is a string that represents the bits as 0 and 1.*/
for ($i = 0; $i < strlen($inString); $i++) {
$inChar = ord(substr($inString,$i,1));
if(isset($BASE32_TABLE[$inChar])) {
$deCompBits .= $BASE32_TABLE[$inChar];
} else {
trigger_error('input to Base32Decode had a bad character: '.$inChar);
return false;
}
}

/* Step 5 */
$padding = strlen($deCompBits) % 8;
$paddingContent = substr($deCompBits, (strlen($deCompBits) - $padding));
if(substr_count($paddingContent, '1')>0) {
trigger_error('found non-zero padding in Base32Decode');
return false;
}

/* Break the decompressed string into octets for returning */
$deArr = array();
for($i = 0; $i < (int)(strlen($deCompBits) / 8); $i++) {
$deArr[$i] = chr(bindec(substr($deCompBits, $i*8, 8)));
}

$outString = join('',$deArr);

return $outString;
}

?>
<?php
// +----------------------------------------------------------------------+
// | Auto-increment ID Obfuscation |
// +----------------------------------------------------------------------+
// | Copyright (c) 2012 MyNikko.com |
// |http://mynikko.blogspot.com/2012/03/auto-increment-id-obfuscation.html|
// +----------------------------------------------------------------------+
function xor_this($string) {
$key = 'JohnnyBeGood';

$text = sprintf('%s', $string);

$outText = '';

for($i=0;$i<strlen($text);) {
for($j=0;$j<strlen($key);$j++,$i++) {
$outText .= $text{$i} ^ $key{$j};
}
}
return $outText;
}

function id_encode($id) {
return base32_encode(xor_this(base_convert(((float) $id) , 10 , 32 )));
}

function id_decode($fakeid) {
return (float) base_convert(xor_this(base32_decode($fakeid)), 32, 10);
}

$test = "1";
printf("%s → %s → %s <br />", $test, id_encode($test), id_decode(id_encode($test)) );
$test = "2";
printf("%s → %s → %s <br />", $test, id_encode($test), id_decode(id_encode($test)) );
$test = "3";
printf("%s → %s → %s <br />", $test, id_encode($test), id_decode(id_encode($test)) );
$test = "100";
printf("%s → %s → %s <br />", $test, id_encode($test), id_decode(id_encode($test)) );
$test = "1000";
printf("%s → %s → %s <br />", $test, id_encode($test), id_decode(id_encode($test)) );
$test = "10000";http://www.blogger.com/img/blank.gif
printf("%s → %s → %s <br />", $test, id_encode($test), id_decode(id_encode($test)) );
$test = "1000000";
printf("%s → %s → %s <br />", $test, id_encode($test), id_decode(id_encode($test)) );
$test = "94256245";
printf("%s → %s → %s <br />", $test, id_encode($test), id_decode(id_encode($test)) );
?>



This actually answers the question here: http://stackoverflow.com/questions/432291/1-1-mappings-for-id-obfuscation

Friday, January 13, 2012

2012 台灣總統大選的選前之夜

依照慣例,我每一組候選人的造勢場合都有去看。



宋楚瑜的人數約在一萬人出頭。當然因為我看的是台北場,所以人數少是一定的,畢竟台北一直是國民黨的票倉,而且也是台灣相對富裕的族群所居住的地區。這次親民黨選得的確很辛苦,連傳單只是小名片一張,小旗子倒還是足夠。依照以前的刻板印象,宋楚瑜的場照理說應該都是外省籍居多。不過這次台北場讓人驚訝的是,居然是本省居多,外省也有,再來才是客家族群(比例大約60:30:10)。年齡當然都是以中老年人居多。他們的精神,令我滿感動的,明明知道希望不高,可是大家還是不離不棄。我相信宋楚瑜為了政黨票,也不可能棄選。這次如果他沒有出來,我想親民黨應該也很難跨越5%的門檻。





馬英九在最後一天的凱道人數,其實比我想像中的少(大約五萬多吧)。年齡層卻比我預計的高了一些。不過國民黨也是最有經濟實力的政黨。我才到場沒多久,就已經被發了三次鴨舌帽(我前兩次都拒絕了,一直到第三次才拿了一頂)。這種「高級品」通常應該要錢的才是啊。讓我非常驚訝的是居然這種高級品都還有一堆沒發完,如果不是當初國民黨預算編太多,就是參加人數不如預期踴躍。族群是本省跟外省都有。





蔡英文的場是在板橋,交通算是最不方便的。因為離捷運站有一段距離。不過光光在接近的時候,就已經看到周圍有人用小跑步的方式在趕往會場。會場外面也是小販群聚。這讓我想起當年民進黨的場子在中山足球場,也是類似的狀況,只是當年外面的攤販除了食物以外,還有賣禁書與成人書籍(沒錯,當年是這樣放在一起賣的)。光光要進入體育場就有點困難,因為入口很擠。而整個運動場真的是大爆滿。族群除了本省跟外省,還有許多觀光客,最多的就是香港人,再來就是歐美人士,我也看到中國交換學生。而且三場的參加者裡面,以蔡英文場的平均年齡是最低的。





雖然造勢場合看人數是不準的,但是我總喜歡觀察一些小地方。其實宋楚瑜的場子是真的三場裡面唯一有明顯地族群融合,也是最弱勢的。當年希特勒演講,旁邊會依照內容奏出配合的背景音樂。這招一直到近年的台灣才漸漸出現。我沒記錯的話,是民進黨先開始用的。當然現在對國民兩黨來說,這都是常識了。不過親民黨的場子卻沒有這麼做(至少台北場沒有),我想親民黨的競選團隊如果不是礙於預算就是人才不足。而馬英九的場子是唯一台北捷運有擺出告示牌的(一出車廂就有寫凱達格蘭大道的方向,不像其他兩場,尤其蔡英文的最難找)。這算是小小的行政不中立嗎?倒也還好,畢竟台北捷運也有專為蔡英文的造勢場合加開了專用列車。這次蔡英文的年輕族群引起了我的注意,因為綠營終於又有正妹出現了(大誤),而且還真不少。而且當蔡英文講出讓女人當家一次的時候,場上所有的女生(不是只有婆婆媽媽喔,因為有不少年輕人)都很激動,然後男生都有點小尷尬,哈哈。我想蔡英文在這次有成功吸引到許多年輕人與婦女的選票。


只用台北的造勢來預測大選是以管窺天,不過我一直認為造勢活動的組成份子是有指標性作用的。因為扣除死忠支持者,多多少少可以看出一些中間選民的動向。我認為這次蔡英文應該會如同2004年一般險勝,而且票數差距會比2004年多一點點。當然這只是我的猜測,準確與否,再過十幾小時就知道了。


至於誰當選會對台灣比較好?我個人天真的以為,其實宋楚瑜當選會最好,因為他的包袱最少。事實證明,無論是誰當選,台灣短期之內既不可能獨立,也不可能獨立。過去四年也證明,即使台灣對中國釋出善意(甚至有點用貞操換經濟的感覺),在經濟上,台灣的民眾感受並不強烈(不過我想大企業家感受應該都很強烈,不然也不會這麼支持了)。我個人以為宋楚瑜是這三人中最有辦法破解藍綠的協調人。我個人相信馬英九與蔡英文的為人,但是馬英九與蔡英文在選後都要面對黨內的壓力,進行政治妥協(以當年考試院長提名人沈富雄被否決及民進黨的不分區立委名單就可以知道黨內有多少壓力)。而當初幫你站台的企業家與政治家,你是否需要報恩?我想多多少少都會有人情壓力在。宋楚瑜雖然是支持終極統一的人,但是在他的任內他也不可能統一。他心裡也一定清楚,他只有這四年。除非他做得非常出色,不然四年後絕對沒有他的份。他只能拼命去幹。國民兩黨其實歷年來,一直用兩岸與賣台做後盾。政績再差(請看2008年民進黨用的口號及今年國民黨用的口號),國民兩黨的死忠支持者都給予其支持候選人一定程度的鼓勵。但是宋只能破釜沈舟地去真正讓台灣人民感受到他的政績,不然四年後,國民兩黨不會給他任何機會的。


我覺得以現階段的台灣,必須不斷地政黨輪替。絕對的權力使人絕對的腐化,陳水扁是一個例子,而目前「完全執政」的國民黨也是一個例子。馬英九真的一無是處嗎?我不覺得,他也有不少的政績令人肯定(多國免簽就是一個例子)。但是黨團以財團為主,忽視人民權益(例如:22K、土地徵收法),我想是他失去那個99%選票的主要原因。做不好,就下台!休息檢討一下,下次再重新出發。