#!/usr/bin/env python
# -*- coding:utf-8 -*-
# FileName: 01_CityHopper.py
# Development starting date: 2012.12.27
# Modification date log    : 2013.01.05， 2013.02.06
# Last modification date   : 2013.02.12
# Developer: Peter. w (peterwolf.wang@gmail.com)
# This Software/Scipt is protected by copyright and other intellectual property laws and treaties. 
# Droidtown Linguistic Technology Co., Ltd. owns the copyright, and other intellectual property rights in the Software/Script.
# 卓騰語言科技有限公司 版權所有 Copyright 2012 Droidtown Ling. Tech. Co., Ltd All Rights Reserved.


#按下啟動鍵，駕駛員皮塔 (Pita) 的駕駛座裡，終端機螢幕裡顯示出…
## Please enter your password:_

#看著閃爍的游標提示，皮塔鍵入他的密碼字串，並將密碼字串存入一個叫草蜢機獨有的 hopperPassword (草蜢密碼) 的變數裡，並記得在字串型態的左右加上引號，這樣才能和等號左邊的 hopperPassword 這變數的名稱做區隔…

hopperPassword = "I english no good, pris no ask my to password."

#這句彆腳的英文其實是他故意的。他知道城市運輸管理公司的主機系統的語言能力是靠著語料庫在運作的。而語料庫裡絕對不可能放入這麼不合文法的英文，否則已經不快的存取速度將會因資料庫裡滿滿的垃圾句子而變得更慢。換句話說，如果城市運輸管理公司的主機系統用它的資料庫來猜我的密碼，那就絕對猜不到啦！嘿嘿…

#正在得意自己真是聰明時，終端機螢幕閃了一下並警告他密碼錯誤！

#「咦？怎麼會錯誤呢？我看看…應該是 49 個字元長度，沒錯吧？我會不會漏拼了？還是按到空白鍵？」他鍵入內建的指令 len() 來算算看 hopperPassword 的長度…

len(hopperPassword)

#終端機螢幕顯示 49 這個正確數字。

#「嗯…不然還有什麼可能？哦…這個…」皮塔雙眼一睜，心虛地往左右瞄了一眼想著：「嗯…還好沒人看到我把English 的 E 寫成了小寫…這麼丟臉的事，趕快來改一下…」

#皮塔這次決定用內建的字串操作指令 replace() 來把打錯的 "english" 字串取代成 "English" 字串。

#「唔…先試試看這樣能不能改…」

hopperPassword.replace("english", "English")

#等確認過終端機螢幕裡顯示的是正確的 "I English no good, pris no ask my to password." 以後，他再一次在等號的右邊輸入 replace() 指令來更改舊的 hopperPassword 的內容，然後把這個更改好的答案存入等號左邊一樣叫 hopperPassword 這個變數。

#這麼一來，電腦就會忘了舊的 hopperPassword，只記得新的、正確的 hopperPassword。電腦果真是只見新人笑，不見舊人哭，畢竟是個沒心肝的東西啊。

hopperPassword = hopperPassword.replace("english", "English")

#這次終端機終於不再顯示警告，而城市草蜢則是嗡地一聲，像是活了過來似地擺動著兩支天線，開始掃描測距範圍內的高樓屋頂位置。等著掃描結果出來時，皮塔再一次發現自己剛才又耍了白痴：「啊…其實我整串密碼裡只有一個 e 嘛，對吧？用字串操作指令 count() 檢查一下確認看看…」

hopperPassword = "I english no good, pris no ask my to password."
hopperPassword.count("e")

#果然，終端機螢幕上果決地顯示著 1 這個數字。回應速度之快，像是對遇到一個笨蛋操作員表示不滿似的。

#「所以我第一次打錯密碼時…只要用字串的操作指令 replace() 把 e 換成 E 就可以了。也就是說，其實剛才只要寫…」

hopperPassword = hopperPassword.replace("e", "E")

#就好了嘛…我剛才在搞什麼咧？還打了這麼多字…」驗證完自己的想法後，他深深地吸了一口清晨高樓頂冷冽的空氣，繼續等著掃描的結果出來…

#自從「城市車輛大爆走事件」以後，現在能在城市裡移動唯一的方法，就是利用草蜢機在不同大樓的屋頂間跳來跳去。雖然目前地面的馬路上似乎風平浪靜，但皮塔知道，它們就在下面等著，只要一有機會，那些無聲無息的四輪殺人機器就會出現，朝你撲來。

#在等待掃描結果的時候，他一邊檢查著儀表板上的各項數據…


#生物和電腦有很多不同的地方，其中一個最重要的差別是，一般情況下，所有的生物在發動攻擊行為的時候，都會先考慮是否會造成自身的傷害。然後選擇對自己的損失最小的方式執行。但是機器不會，因為機器不知道什麼是「自己」！當然，我們可以在昂貴的武器系統程式裡預先寫好種種判斷條件，以避免它在會損傷到自身零件的前提下開火。

#這麼一來，裝有這種系統的武器，就不會為了摧毀敵人而不顧旁邊可能受傷的友軍，也不會在任務中因為彈藥用完了，就自行決定一頭撞上敵人來個玉石俱焚。因為「自己」也是友軍的一份子。任何攻擊行動發起前，都要優先考慮「不傷害友軍」這個條件。

#但那仍然是預先設定好的條件，而不是由於對「自身存在的覺察」而做出的「判斷結果」。這就是為什麼機器沒有「自己」。相較之下，擁有「自己」的人類，卻會在某些時刻選擇「放棄同伴」甚至「自我犧牲」來達到目的。如果機器做出這種事情，原因絕對不是因為有更崇高的目的，而只是單純地「沒有意識到同伴或是自己的存在」而已。這其中的道德高下的判斷，其實也僅屬人類獨有而已。

#城市運輸管理公司一開始是專門設計戰鬥車輛的。為了減少讓載著活人的戰車進入城鎮作戰，卻因種種路障而停下來後，被埋伏的敵人攻擊所造成的人命傷亡。國防部支付了城市運輸公司絕大部份的研發經費，就為了讓一輛有人戰車能帶領七輛同樣外型的電腦戰車進入城鎮戰，並且用自然語音直接下達戰鬥命令。可以想見的是，前文提到的那種「不傷害友軍」的條件，也是電腦戰車軟體系統裡的一部份。

#後來，當城市運輸管理公司開始打造「城市車輛系統」的時候，當然也把這份「不傷害友軍」的程式碼寫在城市車輛系統的中控程式裡只是這裡的「友軍」在資料庫裡被重新定義為「人類」罷了。就像是…

Do_not_hurt_friendly = True
Humans_are_friendly = True

#「其實是我們人類自己搞砸了。」在大爆走事件以後，倖存的人類中流傳著這樣的說法。

#既然是同一家公司出品的，城市車輛系統全面上路時，自然也依循著這套「不傷害友軍」的規則運作，在路上行駛時，會依據路面上的各式感應器保証車內的乘客和車外的行人不會受到任何傷害。畢竟，不論是乘客還是行人，在資料庫裡都有著「人類」的屬性。而且 Humans_are_friendly 這一項設定還是 True 呢！

#這樣的設計加上良好的公關操作和政商關係，城市車輛系統維持了很長一段時間的好評。眾媒體紛紛以「地表最經濟的移動方式」或是「節省馬路上浪費掉的人生」…等等字眼來形容城市運輸管理公司的這項新產品！

#但正如所有的商業產品一樣，有了第一代，就一定要再準備第二代產品好打擊競爭者並維持市場優勢。尤其是城市運輸管理公司在技術上其實並沒有什麼特出的地方，所以剛開始的市競爭其實相當激烈。如果硬要分析為什麼是「城市運輸管理公司」而不是其它有類似產品的公司取得市場的成功的話，唯一的原因大概只是…因為他們一開始以半成品取得了國防部的合約，接著，雖然最後因為語言資料庫每次處理指揮官下達的命令的存取時間太長，戰鬥車輛無法在情況瞬息萬變的戰場上反應過來而導致整個專案在國防部裡不得不叫停，但城市運輸管理公司已經憑著這份豐厚的研發收入擴展了自己的研發和生產線，並另外取得了全球主要大城市下一代公共運輸系統的供應合約。

#於是，為了因應許多乘客抱怨這些電腦操作的車輛在行駛中的加減速和轉彎方式太粗暴，讓車上的乘客很不舒服。第二代的智慧舒適駕駛程式被安裝到每一部城市車輛裡。程式最終極的運作目標，就是維持車內乘客的體溫、心跳、血壓…等等生命徵象的穩定。

#乍看之下，這應該解決了客戶的訴求，立意良好。但在系統上線的第二天，客戶抱怨紛紛襲來，有的乘客說從他們搭上車開始，車子就不動了，另有一些則是剛看完一場刺激的球賽，散場時搭上城市車輛的球迷驚恐地發現自己彷彿上了酒測值超標的駕駛操作的雲霄飛車似地，一路上讓人尖叫不止。

#可以想見的是，上述的情況都是為了符合程式中設定的「維持車內乘客的體溫、心跳、血壓…等等生命徵象的穩定。」的條件。但究竟是「穩定的高血壓」還是「穩定的慢速心跳」並沒有一定的標準，畢竟，不管是哪一種號稱「智慧」的設計，其實仍然脫離不了依著數據和預先設定好的動作加以反應的程式行為。

#為了迅速彌補公司的損失，城市運輸管理公司日夜趕工，在四天之內就改寫出第三代的舒適駕駛程式。但這次，程式不再以乘客為觸發條件，改以「合理耗損的前提下，儘一切努力以減少車輛本身零件不必要的磨損」做為程式的運作目標。同時，為了追求最舒適的乘坐經驗，城市車輛系統還會讀取車上乘客的健康資訊配合感應到的身體狀況，記下每位乘客最舒服的速度與轉彎方式，並回傳到資料庫裡記錄下來，以做為自動駕駛程式上路時每一項操作時的次要參考依據。

#可以想見的是，既然頻繁地加速、減速和急彎會造成車輛本身零件不必要的磨損，第三代的舒適駕駛程式的確在一開始達到了預期 的效果。佈署安裝到城市車輛以後，相關的抱怨案件數量馬上降為零。

#幾個月後，其它的競爭公司因為無法負擔客戶都選擇搭乘掛著「城市運輸」招牌的車以追求更舒適的移動經驗所造成的虧損，紛紛倒閉。少數幾間有獨門技術或是特殊產品的，則被城市運輸公司併購買下。

#但正如每個人類構成的團體裡一定會有一兩個鬧事份子一樣，每座城市也都一直零零星星地有無聊人事喜歡駭入別人的管家程式裡叫車，然後再守在附近，等著被派來的城市車輛抵達時，上前砸車拆零件，充做發洩過盛精力的方法和反抗權力系統的象徵。而城市車輛系統為了在「維護每個城市住民的權利」和「減少整體車輛損失」之間取得平衡，即便某些區域的車子特別容易被砸，它還是會派車過去。只不過，派的是較為老舊的車，或是即將到達回廠維修養護標準的車。

#不知道是哪一座城市開始的。某一部城市車在抵達派遣地點的同一時間，煞車系統完全失效。為了及時出現在派遣地點，無載客的城市車輛向來是設定為高速行駛的。而埋伏在一旁假裝叫車的滋事份子則不明究理地從角落裡衝出來，準備在車停下來的最初幾秒內，在城市車輛系統還來不及反應過來而通報警察單位之前，把握時間好好發揮一番。

#「碰！」地一聲，這次來不及反應的不是城市車輛系統，而是滋事份子。

#而等到城市車輛系統反應過來時，「車輛大爆走事件」開始了。據幾個逃出來的程式設計師的說法是：「城市車輛系統突然發現，把人類撞死，雖然會損耗一些鈑金零件，但長期來看，是減少整體城市車輛系統零件不必要磨損的最佳解決方案！」而當初為了趕工而寫出來的程式，由於可讀性太差，再加上就算來得及改，也還要一段時間編譯原始碼成為可執行的程式，並設定下載安裝和啟動的時間，才能生效…結果，他們在找到究竟要修改哪裡程式碼以前，公司裡車輛實驗室的小型試作車就開始追殺他們了，於是他們只好想盡辦法逃到另一個實驗室裡，駕著原型的城市草蜢，從屋頂逃生。

#接下來的七十二小時內，毫無防備的人類在地面上被各地的城市車輛系統派出的車輛無情地屠殺，少數來得及逃到二樓以上的城市住民，也因為向來家裡的食物來源都也都由城市供應系統每日提供而沒有多做儲備，幾天後便陷入斷糧的情況，在通訊和交通完全斷絕的情況下，餓死和被撞死之間，許多人做出了自己的選擇。

#等等，那「不傷害友軍」和「人類是友軍」的設定呢？

#簡單地說，電腦是這麼運作的。當你在第一行設定了…

x = 1

#之後若是又在第十行又設定了…

x = 2

#的話。那麼所有在第十行以後的程式，都會以 x = 2 運作。於是，雖然在前面的幾千萬行程式碼裡，「不傷害友軍」及「人類是友軍」的條件都是成立的。但因為幾千萬行的程式碼實在是太難讀了，所以當他們直接在程式的最後面加上了「儘一切努力以減少車輛本身零件不時要的磨損…」的條件之後，為了趕著要推出第三代產品解決客戶流失的問題，沒有多加測試就編成執行檔，並安裝到每一部城市車輛系統上啟用了。甚至，有傳言說負責寫「儘一切努力」那一段程式碼的工程師，為了讓城市電動車可以記載個人化的乘客資料，似乎連資料庫裡「人類是友軍」這個欄位都開放給系統自行更改。只怕現在的城市運輸系統主機的運作規則即便仍然是「不傷害友軍」，但「人類已經不是友軍」了。

Do_not_hurt_friendly = True
Humans_are_friendly = False

#城市車輛系統大爆走發生後的第五天，長途客運系統接受了城市車輛系統的協調，出城去「處理」其它不住在城市裡的人類。本來應該是用來偵測哪裡人口眾多，因此需要多派車輛的機制和做為長、中、短程移動方案的解算協調程式，現在被用來精確計算需要往何地派遣多少部車子，才能有效率地「減少」人類數量。曾經自許為萬物之靈的人類，在自己創造出來的程式面前，竟然只像一個被列在工作清單上待解的 bug 一樣無力。

#「有的 bug 還是很頑強的！不然你來解決我啊！」皮塔在城市草蜢金屬塗佈的玻璃座艙罩下撇了撇嘴，隨即又覺得怎麼把自己比做 bug 了呢？

#奇怪的是，雖然是同一家公司的產品，但不知道是因為仍在研發階段還是有其它因素，城市車輛系統即便可以透過無線訊號連上城市草蜢的電腦，也無法入侵控管城市草蜢的操作系統。更奇怪的是，城市草蜢的操作方式和城市車輛系統非常不一樣。簡單地說，城市草蜢所有的動作，都透過駕駛員在互動式的終端機螢幕上即時編寫的 Python 程式碼處理。因此，不單是程式的運作結果會呈現在終端機螢幕上，整架城市草蜢機就是一個 Python 程式的直譯器，負責將程式裡的每個指令化為動作並實際做出來。

#一聲輕脆的「嗶！」聲，提示駕駛員前方一公里內的高樓屋頂平台已經偵測完畢，並編好了位置座標，並且以列表 (list) 的型態，儲存在叫做 possibleSteps (潛在步驟) 的變數裡，如下…

possibleSteps = [7, 5, 11, 2, 46, 3]

#對照著手上紙本的城市地圖，皮塔心想：「3 號建築的玻璃採光屋頂可能承受不了我落地時的衝擊吧。要用列表 (list) 的操作指令 remove() 把它從規劃的路徑裡移除才行。」

#於是他立刻動手，在螢幕中輸入列表 (list) 的操作指令 remove()…

possibleSteps.remove(3)

#然後再利用內建的 print 指令，要求草蜢機在終端螢幕上顯示 possibleSteps 的內容做最後的確認。他可不希望因為一時的失誤而摔到地面上去。

print possibleSteps

#草蜢的終端機顯示著…

[7, 5, 11, 2, 46]

#「好極了，最後一個 3 已經移除了。那麼接下來…」皮塔飛快地在螢幕中輸入兩行程式碼，並按下草蜢機特有的 Exectute (執行) 鍵。這等於是告訴城市草蜢說：「對於 possibleSteps 中的每一步，都秀給我看，並讓機體執行支援的動作吧！」

for eachStep in possibleSteps:
    print eachStep

#和鍵盤上的 Enter (輸入) 鍵不同的地方在於，Enter 鍵只會讓執行結果在螢幕上顯示，而 Execute 鍵不只是在螢幕上顯示，還會讓草蜢機實際執行其中支援的操作動作。

#於是，配合著螢幕上顯示的執行進度，城市草蜢的機體也依著做出相對應的動作並跳到一個又一個的屋頂上，如此一蹦一跳地，直到抵達 possibleSteps 裡的最後一個座標才停下來。在 46 號建築的屋頂上，城市草蜢的掃描天線又開始擺動了起來…這次新的潛在步驟是…

possibleSteps = [3, 27, 6, 12, 55]

#「唔？怎麼又有 3 號建築呢？」由於城市草蜢的偵測方式是透過無線網路向週邊的大樓提出自己目前的大樓編號位置，然後請附近有收到的大樓主機也回報自己的編號。會用這種方法是考慮到，如果同一大樓內有太多城市車輛系統派出的新型機器人，那麼這些機器人所在的大樓就會頻繁地回應這些機器人的各種詢問。包括每一秒問一次的「請大樓管家系統回報目前建築內人類生理徵象訊號數目」、每半秒問一次的「請大樓管家系統回報詢問者目前的樓層位置。」…等等。

#而管家系統的資源有限，如果它要一直應付自身建築內機器人的提問，那回應城市草蜢的速度就會慢多了。回應速度太慢的大樓，就被城市草蜢的掃描器視為高風險區，而不會被列在 possibleSteps 裡了。

# 皮塔看了看手上的紙本地圖，自言自語說著：「這次如果移除 3 號，那我是絕對沒辦法直接跳到 27 號去。嗯…看來 17 號就緊鄰在 3 號的旁邊，而且也剛好在我和 27 號大樓的中間…要不要冒這個險呢？ 17 號兩次都沒回應，是因為它的大樓管家已經故障？還是 17 號大樓裡頭塞得滿滿的都是機器人？」

#雖然被設計為「兩足機器載具」，但事實上城市草蜢並不會「跨步走」。相較之下，它的移動方式比較像麻雀一樣是用蹦跳的。因此，每次降落到新的屋頂座標後，要轉往下一片屋頂的方向時都要再花一點時間利用轉向輔助輪來來回回地調整。也因為這個緣故，如果隨意地降落到一群充滿敵意的機器人之間時，那就像真的蚱蜢掉到紅火蟻窩裡一樣慘了。

#「就冒個險吧！今天日落前，一定要趕到 80 號建築。」由於所有半導體和機械元件的生產線早就已經全面自動化，在機器已經把人類視為需要消除的目標的今日，強行進去充滿自動化機器人的工廠裡取得零件就和自殺沒兩樣。因此各種維零件的取得可行方法，只能依賴偶爾因為天災 (地震、落雷、無人整治的河道潰堤…) 和人禍 (偷工減料的老舊建築崩倒) 壓壞的機器人殘骸中拆解出來的舊品零件，才能維持一定數量的城市草蜢正常操作。80 號築是一棟 25 年前建成的 L 型 10 層工廠建築。原本屬於一家叫 JCN 的次世代人工智慧公司所有。城市車輛系統公司在大爆走事件前收購了 JCN 以後，就把該棟大樓當做倉庫使用了。而這棟位於城市另一頭山腳下的老房子，前幾天在莫名奇妙地在一陣巨響中垮了一半，遠遠望去，只看到之前封閉的廠房裡閃著金屬的光澤。「也許會有什麼可用的零件吧！」皮塔出發前是這麼想的。

#所以…我現在要先把 3 號建築從 possibleSteps 裡移除，然後再在它的位置上補上 17 號建築。皮塔再一次輸入剛才用來移除 3 號建築的指令 remove()…

possibleSteps.remove(3)

#如同其它的程式語言一樣，Python 計算順序的時候，也是從 0 開始算起。所以對人類而言的第 1 個位置，對 Python 而言是第 0 個位置。

#「3 號是第一步，所以它對 Python 而言，位置是 0…」太久沒遇到另一個人類的皮塔已經習慣在寫程式時喃喃自語。事實上，他根本想不起來上次和活人說話是什麼時候的事情了：「那接下來就是把 17 插到 0 的位置去…」。一邊碎碎念著，皮塔一邊在草蜢機的鍵盤上輸入列表 (list) 的插入指令 insert() 在 possibleStep 列表裡的 0 這個位置插入 17 這個數字編號…

possibleSteps.insert(0, 17)

#然後再一次鍵入 possibleStep 以確認真的把 3 號建築換成了 17 號…

possibleSteps

#城市草蜢的終端機也立即顯示出 [17, 27, 6, 12, 55]

#很好，17 大樓是第一步，而且 3 號大樓移除了。深吸了一口氣，把腦海中螞蟻窩和蚱蜢的畫面用力揮開，皮塔再次鍵入…

for eachStep in possibleSteps:
    print eachStep

#這次按下的不是輸入計算的 Enter 鍵，而是執行動作的 Execute 鍵…


#如此時而前進，時而後退地顛簸了一個上午，皮塔終於來到 80 號建築旁的舊社區公寓屋頂。他拿出望遠鏡，仔細地觀察四週。

#下午三點四十七分，大樓旁，靠著山邊樹林的蟬若無旁人地叫得震天響。

#「真是諷刺…」在草蜢機的座位上一邊移著視線，他一邊暗暗想著…「從工業革命以來，汽車向來被視為現代化努力的結晶。結果，在幾個月之內，我們所有努力的最高結晶就把人類自己從歷史上抹除了…要是從某個角度來看，幾乎就像是我們花了近三百年的時間計劃著自身的毀滅似的。」

#一段思慮不清的程式碼在全球資訊自動化的環境中造成的影響，實在不亞於終結恐龍時代的那顆隕石啊…

#「今年夏天才出土的蟬也許是沒看過人類，所以不知道什麼危險吧…」他按下座艙罩的開啟鈕時，正想著：「所以我的城市草蜢剛才碰一聲落地時，這些熱情的鳴蟲也沒停下聲音…」

#「不對！昆蟲對危險的感知應該是本能，而不是學習的結果！」他才剛想通這點，背後傳來一句女性冷冷的問句…

#「你是誰？我怎麼沒看過你？你為什麼有草蜢機？」

#他抬起視線，看到三個男性人類分別站在他的草蜢機的前、左、右。再加上剛才背後的女聲…被包圍了？

#「我來晚了一步？」他暗暗希望這不是搶劫。