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
25using 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
45KBlocksGameLogic* mpKBlocksGameLogic;
46KBlocksPlayManager* mpKBlocksPlayManager;
47KBlocksPlayNetwork* mpKBlocksPlayNetwork;
48KBlocksWin* mpKBlocksWindow;
49KBlocksDisplay* mpKBlocksDisplay;
50KBlocksAppThread* mpKBlocksAppThread;
51
52KBlocksAIPlayer** maAIPlayers;
53KBlocksKeyboardPlayer** maHumanPlayers;
54
55enum KBlocksGameMode
56{
57 KBlocksGame_DesktopMode = 0,
58 KBlocksGame_EngineMode,
59 KBlocksGame_GuiMode,
60 KBlocksGame_PlayerMode,
61 KBlocksGame_ReplayMode,
62 KBlocksGame_MaxMode_Count
63};
64
65int 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
87int 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
141int 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
174int 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
230int 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
312int 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