1 | /*************************************************************************** |
2 | * KBlocks, a falling blocks game for KDE * |
3 | * Copyright (C) 2009 Mauricio Piacentini <mauricio@tabuleiro.com> * |
4 | * Zhongjie Cai <squall.leonhart.cai@gmail.com> * |
5 | * * |
6 | * This program is free software; you can redistribute it and/or modify * |
7 | * it under the terms of the GNU General Public License as published by * |
8 | * the Free Software Foundation; either version 2 of the License, or * |
9 | * (at your option) any later version. * |
10 | ***************************************************************************/ |
11 | #include <time.h> |
12 | #include <string> |
13 | #include <vector> |
14 | |
15 | #include <kapplication.h> |
16 | #include <kcmdlineargs.h> |
17 | #include <kaboutdata.h> |
18 | #include <klocale.h> |
19 | #include <kglobal.h> |
20 | |
21 | #include <QString> |
22 | #include <QList> |
23 | #include <QByteArray> |
24 | |
25 | using namespace std; |
26 | |
27 | #include "KBlocksConfigManager.h" |
28 | |
29 | #include "KBlocksGameLogic.h" |
30 | #include "KBlocksPlayManager.h" |
31 | #include "KBlocksPlayNetwork.h" |
32 | #include "KBlocksWin.h" |
33 | #include "KBlocksDisplay.h" |
34 | #include "KBlocksRepWin.h" |
35 | |
36 | #include "KBlocksAppThread.h" |
37 | |
38 | #include "KBlocksPlayNetwork.h" |
39 | #include "AI/KBlocksAIPlayer.h" |
40 | #include "KBlocksKeyboardPlayer.h" |
41 | |
42 | #include "KBlocksNetServer.h" |
43 | #include "KBlocksNetClient.h" |
44 | |
45 | KBlocksGameLogic* mpKBlocksGameLogic; |
46 | KBlocksPlayManager* mpKBlocksPlayManager; |
47 | KBlocksPlayNetwork* mpKBlocksPlayNetwork; |
48 | KBlocksWin* mpKBlocksWindow; |
49 | KBlocksDisplay* mpKBlocksDisplay; |
50 | KBlocksAppThread* mpKBlocksAppThread; |
51 | |
52 | KBlocksAIPlayer** maAIPlayers; |
53 | KBlocksKeyboardPlayer** maHumanPlayers; |
54 | |
55 | enum KBlocksGameMode |
56 | { |
57 | KBlocksGame_DesktopMode = 0, |
58 | KBlocksGame_EngineMode, |
59 | KBlocksGame_GuiMode, |
60 | KBlocksGame_PlayerMode, |
61 | KBlocksGame_ReplayMode, |
62 | KBlocksGame_MaxMode_Count |
63 | }; |
64 | |
65 | int gameDesktopMode(const KApplication& app) |
66 | { |
67 | // Desktop User Mode |
68 | mpKBlocksGameLogic = new KBlocksGameLogic(2); |
69 | mpKBlocksGameLogic->setGameSeed(time(0)); |
70 | mpKBlocksGameLogic->setGamePunish(true); |
71 | mpKBlocksGameLogic->setGameStandbyMode(true); |
72 | mpKBlocksGameLogic->setInitInterval(500); |
73 | mpKBlocksGameLogic->setLevelUpInterval(25); |
74 | |
75 | mpKBlocksPlayManager = new KBlocksPlayManager(mpKBlocksGameLogic, 2); |
76 | |
77 | mpKBlocksWindow = new KBlocksWin(mpKBlocksGameLogic, mpKBlocksPlayManager, 2, 1); |
78 | mpKBlocksWindow->setUpdateInterval(50); |
79 | mpKBlocksWindow->setGamesPerLine(4); |
80 | mpKBlocksWindow->setGameAnimEnabled(true); |
81 | mpKBlocksWindow->setWaitForAllUpdate(true); |
82 | mpKBlocksWindow->show(); |
83 | |
84 | return app.exec(); |
85 | } |
86 | |
87 | int gameEngineMode(KBlocksConfigManager * config) |
88 | { |
89 | int gameCount; |
90 | bool sameSeq; |
91 | bool hasAttack; |
92 | bool standbyMode; |
93 | bool hasHuman; |
94 | bool sendLimit; |
95 | string serverIP; |
96 | |
97 | string recordFile; |
98 | string recordType; |
99 | bool recordBinary; |
100 | |
101 | config->GetKeyInt("Engine" , "GameCount" , &gameCount, 1); |
102 | config->GetKeyBool("Engine" , "SameSequence" , &sameSeq, true); |
103 | config->GetKeyBool("Engine" , "HasAttack" , &hasAttack, true); |
104 | config->GetKeyBool("Engine" , "Synchronized" , &standbyMode, false); |
105 | config->GetKeyBool("Engine" , "HasHuman" , &hasHuman, false); |
106 | config->GetKeyBool("Engine" , "SendLimit" , &sendLimit, false); |
107 | config->GetKeyString("Engine" , "ServerIP" , &serverIP, "127.0.0.1:10086" ); |
108 | |
109 | config->GetKeyString("RecordReplay" , "Record" , &recordFile, "" ); |
110 | config->GetKeyString("RecordReplay" , "Type" , &recordType, "binary" ); |
111 | recordBinary = recordType.find("text" ) != 0; |
112 | |
113 | printf("Creating game engine...\n" ); |
114 | printf("\tGame Count = %d\n" , gameCount); |
115 | printf("\tSame Sequence = %s\n" , sameSeq ? "true" : "false" ); |
116 | printf("\tHas Attack = %s\n" , hasAttack ? "true" : "false" ); |
117 | printf("\tSynchronized = %s\n" , standbyMode ? "true" : "false" ); |
118 | printf("\tHas Human = %s\n" , hasHuman ? "true" : "false" ); |
119 | printf("\tSpeed Limit = %s\n" , sendLimit ? "true" : "false" ); |
120 | mpKBlocksGameLogic = new KBlocksGameLogic(gameCount, true); |
121 | mpKBlocksGameLogic->setGameSeed(sameSeq ? time(0) : -time(0)); |
122 | mpKBlocksGameLogic->setGamePunish(hasAttack); |
123 | mpKBlocksGameLogic->setGameStandbyMode(standbyMode); |
124 | mpKBlocksGameLogic->setInitInterval(hasHuman ? 500 : 0); |
125 | mpKBlocksGameLogic->setLevelUpInterval(hasHuman ? 25 : 0); |
126 | printf("Done...\n" ); |
127 | |
128 | printf("Creating network server...\n" ); |
129 | printf("\tServer IP = %s\n" , serverIP.c_str()); |
130 | printf("\tRecord File = %s\n" , recordFile.c_str()); |
131 | printf("\tRecord Type = %s\n" , recordBinary ? "Binary" : "Text" ); |
132 | KBlocksNetServer* mpKBlocksServer = new KBlocksNetServer(mpKBlocksGameLogic, serverIP.c_str()); |
133 | mpKBlocksServer->setSendLength(sendLimit ? 10 : 0, sendLimit ? 1 : 0); |
134 | mpKBlocksServer->setRecordFile(recordFile.c_str(), recordBinary); |
135 | printf("Done...\n" ); |
136 | |
137 | printf("Executing game engine and network server...\n" ); |
138 | return mpKBlocksServer->executeGame(gameCount, standbyMode); |
139 | } |
140 | |
141 | int gameGuiMode(KBlocksConfigManager * config, const KApplication& app) |
142 | { |
143 | int gameCount; |
144 | int gamesPerLine; |
145 | int updateInterval; |
146 | int localPort; |
147 | string serverIP; |
148 | |
149 | config->GetKeyInt("Gui" , "GameCount" , &gameCount, 1); |
150 | config->GetKeyInt("Gui" , "GamesPerLine" , &gamesPerLine, 4); |
151 | config->GetKeyInt("Gui" , "UpdateInterval" , &updateInterval, 1000); |
152 | config->GetKeyInt("Gui" , "LocalPort" , &localPort, 10088); |
153 | config->GetKeyString("Gui" , "ServerIP" , &serverIP, "127.0.0.1:10086" ); |
154 | |
155 | printf("Creating game gui...\n" ); |
156 | printf("\tGame Count = %d\n" , gameCount); |
157 | printf("\tGames Per Line = %d\n" , gamesPerLine); |
158 | printf("\tUpdate Interval = %d\n" , updateInterval); |
159 | printf("\tLocal Port = %d\n" , localPort); |
160 | printf("\tServer IP = %s\n" , serverIP.c_str()); |
161 | mpKBlocksDisplay = new KBlocksDisplay(gameCount, serverIP, localPort); |
162 | mpKBlocksDisplay->setGamesPerLine(gamesPerLine); |
163 | mpKBlocksDisplay->setUpdateInterval(updateInterval); |
164 | mpKBlocksDisplay->show(); |
165 | printf("Done...\n" ); |
166 | |
167 | printf("Starting game gui...\n" ); |
168 | mpKBlocksDisplay->startDisplay(); |
169 | printf("Done...\n" ); |
170 | |
171 | return app.exec(); |
172 | } |
173 | |
174 | int gameReplayMode(KBlocksConfigManager * config, const QApplication& app) |
175 | { |
176 | int gamesPerLine; |
177 | int updateInterval; |
178 | int stepLength; |
179 | string snapshotFolder; |
180 | string snapshotFile; |
181 | string recordFile; |
182 | string recordType; |
183 | bool recordBinary; |
184 | |
185 | config->GetKeyInt("RecordReplay" , "GamesPerLine" , &gamesPerLine, 4); |
186 | config->GetKeyInt("RecordReplay" , "UpdateInterval" , &updateInterval, 100); |
187 | config->GetKeyInt("RecordReplay" , "StepLength" , &stepLength, 100); |
188 | config->GetKeyString("RecordReplay" , "SnapshotFolder" , &snapshotFolder, "./snapshot/" ); |
189 | config->GetKeyString("RecordReplay" , "SnapshotFile" , &snapshotFile, "" ); |
190 | config->GetKeyString("RecordReplay" , "Record" , &recordFile, "" ); |
191 | config->GetKeyString("RecordReplay" , "Type" , &recordType, "binary" ); |
192 | recordBinary = recordType.find("text" ) != 0; |
193 | |
194 | if (recordFile.empty()) |
195 | { |
196 | printf("Error loading replay file: File name is empty!\n" ); |
197 | return -1; |
198 | } |
199 | |
200 | printf("Creating game gui...\n" ); |
201 | printf("\tGames Per Line = %d\n" , gamesPerLine); |
202 | printf("\tUpdate Interval = %d\n" , updateInterval); |
203 | printf("\tStep Length = %d\n" , stepLength); |
204 | printf("\tSnapshot Folder = %s\n" , snapshotFolder.c_str()); |
205 | printf("\tSnapshot File = %s\n" , snapshotFile.c_str()); |
206 | printf("\tRecord File = %s\n" , recordFile.c_str()); |
207 | printf("\tRecord Type = %s\n" , recordBinary ? "Binary" : "Text" ); |
208 | |
209 | KBlocksRepWin* mpKBlocksRepWin = new KBlocksRepWin(recordFile.c_str(), recordBinary); |
210 | if (!mpKBlocksRepWin->replayLoaded()) |
211 | { |
212 | printf("Error loading replay file: Failed to load replay file!\n" ); |
213 | return -2; |
214 | } |
215 | mpKBlocksRepWin->setGamesPerLine(gamesPerLine); |
216 | mpKBlocksRepWin->setUpdateInterval(updateInterval); |
217 | mpKBlocksRepWin->setReplayStepLength(stepLength); |
218 | mpKBlocksRepWin->setSnapshotFolder(snapshotFolder.c_str()); |
219 | mpKBlocksRepWin->setSnapshotFilename(snapshotFile.c_str()); |
220 | mpKBlocksRepWin->show(); |
221 | printf("Done...\n" ); |
222 | |
223 | printf("Starting game gui...\n" ); |
224 | mpKBlocksRepWin->startReplay(); |
225 | printf("Done...\n" ); |
226 | |
227 | return app.exec(); |
228 | } |
229 | |
230 | int gamePlayerMode(KBlocksConfigManager * config, const KApplication& app) |
231 | { |
232 | bool hasHuman = false; |
233 | int playerCount; |
234 | int localPort; |
235 | string serverIP; |
236 | |
237 | config->GetKeyInt("Player" , "PlayerCount" , &playerCount, 1); |
238 | config->GetKeyInt("Player" , "LocalPort" , &localPort, 10090); |
239 | config->GetKeyString("Player" , "ServerIP" , &serverIP, "127.0.0.1:10086" ); |
240 | |
241 | printf("Creating game player manager...\n" ); |
242 | printf("\tPlayer Count = %d\n" , playerCount); |
243 | printf("\tLocal Port = %d\n" , localPort); |
244 | printf("\tServer IP = %s\n" , serverIP.c_str()); |
245 | mpKBlocksPlayNetwork = new KBlocksPlayNetwork(playerCount, serverIP, localPort); |
246 | printf("Done...\n" ); |
247 | |
248 | printf("Adding game players...\n" ); |
249 | maAIPlayers = new KBlocksAIPlayer*[playerCount]; |
250 | maHumanPlayers = new KBlocksKeyboardPlayer*[playerCount]; |
251 | for(int i = 0; i < playerCount; i++) |
252 | { |
253 | maAIPlayers[i] = 0; |
254 | maHumanPlayers[i] = 0; |
255 | |
256 | char tmpBuf[256]; |
257 | sprintf( tmpBuf, "PlayerType%d" , i+1 ); |
258 | string tmpType = string(tmpBuf); |
259 | sprintf( tmpBuf, "PlayerName%d" , i+1 ); |
260 | string tmpName = string(tmpBuf); |
261 | config->GetKeyString("Player" , tmpType, &tmpType, "AI" ); |
262 | config->GetKeyString("Player" , tmpName, &tmpName, "NoName" ); |
263 | |
264 | printf("\tNew Player (%d) Type = %s\n" , i, tmpType.c_str()); |
265 | printf("\t Name = %s\n" , tmpName.c_str()); |
266 | if (tmpType.find("ai" ) != tmpType.npos) |
267 | { |
268 | maAIPlayers[i] = new KBlocksAIPlayer(tmpName); |
269 | mpKBlocksPlayNetwork->addGamePlayer(maAIPlayers[i]); |
270 | } |
271 | else if (tmpType.find("human" ) != tmpType.npos) |
272 | { |
273 | maHumanPlayers[i] = new KBlocksKeyboardPlayer(NULL, tmpName, true); |
274 | mpKBlocksPlayNetwork->addGamePlayer(maHumanPlayers[i]); |
275 | hasHuman = true; |
276 | } |
277 | } |
278 | printf("Done...\n" ); |
279 | |
280 | printf("Starting play manager...\n" ); |
281 | mpKBlocksPlayNetwork->startGame(); |
282 | |
283 | int ret = 0; |
284 | if (hasHuman) |
285 | { |
286 | mpKBlocksAppThread = new KBlocksAppThread(mpKBlocksPlayNetwork); |
287 | printf("Executing play manager...\n" ); |
288 | mpKBlocksAppThread->start(); |
289 | |
290 | printf("Executing keyboard window...\n" ); |
291 | ret = app.exec(); |
292 | |
293 | printf("Terminating play manager execution...\n" ); |
294 | mpKBlocksPlayNetwork->cancelExecute(); |
295 | } |
296 | else |
297 | { |
298 | printf("Executing...\n" ); |
299 | ret = mpKBlocksPlayNetwork->execute(); |
300 | } |
301 | |
302 | printf("Stopping play manager...\n" ); |
303 | mpKBlocksPlayNetwork->stopGame(); |
304 | |
305 | printf("Clearing game players...\n" ); |
306 | mpKBlocksPlayNetwork->clearGamePlayer(); |
307 | |
308 | printf("Exit program...\n" ); |
309 | return ret; |
310 | } |
311 | |
312 | int main (int argc, char *argv[]) |
313 | { |
314 | // Game abouts... |
315 | KAboutData aboutData( "kblocks" , 0, |
316 | ki18n("KBlocks" ), |
317 | "0.3" , |
318 | ki18n("A falling blocks game for KDE" ), |
319 | KAboutData::License_GPL, |
320 | ki18n("(c) 2007, Mauricio Piacentini" ) ); |
321 | aboutData.addAuthor(ki18n("Mauricio Piacentini" ), ki18n("Author" ), "piacentini@kde.org" ); |
322 | aboutData.addAuthor(ki18n("Dirk Leifeld" ), ki18n("Developer" ), "dirkleifeld@yahoo.de" ); |
323 | aboutData.addAuthor(ki18n("Zhongjie Cai" ), ki18n("New design of KBlocks for AI and tetris research platform" ), "squall.leonhart.cai@gmail.com" ); |
324 | aboutData.addCredit(ki18n("Johann Ollivier Lapeyre" ), ki18n("Oxygen art for KDE4" ), "johann.ollivierlapeyre@gmail.com" ); |
325 | |
326 | // Command line argument options |
327 | KCmdLineOptions options; |
328 | |
329 | options.add("mode <game mode>" , ki18n("Setup kblocks game running mode.\n\t0 = Desktop Mode\t1 = Game Engine Mode\n\t2 = Gui Mode\t3 = Player Mode" ), "0" ); |
330 | options.add("conf <configuration file>" , ki18n("Setup the configuration file for tetris researcher mode. Not for desktop users." ), "default.conf" ); |
331 | |
332 | KCmdLineArgs::init( argc, argv, &aboutData ); |
333 | KCmdLineArgs::addCmdLineOptions( options ); |
334 | KCmdLineArgs *args = KCmdLineArgs::parsedArgs(); |
335 | |
336 | // Application |
337 | KApplication app; |
338 | KGlobal::locale()->insertCatalog( QLatin1String( "libkdegames" )); |
339 | |
340 | // Get game mode |
341 | int mGameMode = args->getOption("mode" ).toInt(); |
342 | |
343 | QByteArray tmpFileArray = args->getOption("conf" ).toLatin1(); |
344 | const char *tmpFileChar = tmpFileArray.data(); |
345 | KBlocksConfigManager* config = new KBlocksConfigManager(); |
346 | config->LoadConfigFile(string(tmpFileChar)); |
347 | |
348 | int mResult = 0; |
349 | switch(mGameMode) |
350 | { |
351 | case KBlocksGame_DesktopMode: |
352 | mResult = gameDesktopMode(app); |
353 | break; |
354 | case KBlocksGame_EngineMode: |
355 | mResult = gameEngineMode(config); |
356 | break; |
357 | case KBlocksGame_GuiMode: |
358 | mResult = gameGuiMode(config, app); |
359 | break; |
360 | case KBlocksGame_PlayerMode: |
361 | mResult = gamePlayerMode(config, app); |
362 | break; |
363 | case KBlocksGame_ReplayMode: |
364 | mResult = gameReplayMode(config, app); |
365 | break; |
366 | } |
367 | |
368 | return mResult; |
369 | } |
370 | |
371 | |