1 // Untahris (Common Playground)
2 // copyright (C) 2006 longuens@users.sourceforge.net
3 // Released under GNU General Public License (see the file COPYING)
4 // --------------------------------------------------------------
5 // Header file for everything.
6 
7 #include <vector>
8 #include <string>
9 #include <SDL/SDL.h>
10 #include <SDL/SDL_ttf.h>
11 #include <SDL/SDL_mixer.h>
12 
13 using namespace std;
14 
15 #define MAXX 128
16 #define MAXY 128
17 
18 #define NEVER 2000000000
19 
20 int ky[4] = {-1, 0, 1, 0};
21 int kx[4] = {0, 1, 0, -1};
22 
23 typedef char int8;
24 typedef short int16;
25 typedef long int32;
26 typedef long long int64;
27 
28 enum PlayerKey {
29   keyUp,
30   keyRight,
31   keyDown,
32   keyLeft,
33   keyFire,
34   keyEarth,
35   keyAir,
36   keyWater,
37   // fake keys
38   keyLMB,
39   keyRMB,
40   keyMoveMouse,
41   keyJoinGame
42   };
43 
44 char* ctnames = ".#Xabcdefghi0FGLSRjklmxw";
45 
46 enum CellType {
47   cFree,
48   cBreakWall,
49   cPermaWall,
50 
51   cSnakeHead,
52   cSnakeDead,
53   cSnakeLeft,
54   cSnakeRight,
55   cSnakeUp,
56   cSnakeDown,
57   cSnakeTRON,
58 
59   cTetris,
60   cTetrisDown,
61 
62   cBig,
63 
64   cCannonF,
65   cCannonA,
66 
67   cBonusLevel,
68   cBonusScore,
69   cBonusAmmo,
70 
71   cCastleWall,
72 
73   cBomb1,
74   cBomb2,
75   cExplosion,
76 
77   cXunux,
78   cXunuxStable
79   };
80 
81 struct TBuffer;
82 
83 enum IconId {
84   icFree, icBreak, icPerma,
85   icAmmo, icLevel, icScore,
86   icThrust, icBall, icBullet, icBomber, icBomb1, icBomb2, icSpawn,
87   icExplosion, icExplosion1, icExplosion2, icExplosion3,
88   icCastle, icCannon, icCannonA, icCannonP, icTarget,
89   icWorm, icBazooka, icXunux, icIncastle,
90   icLastIcon
91   };
92 
93 // display's icon indexed by given ID
94 #define Ic(x) icons[int(x)]
95 #define DIc(x) ow()->icons[int(x)]
96 
97 static const int numIcons = int(icLastIcon);
98 
99 static char* iconnames[numIcons] = {
100   "FREE", "BREAK", "PERMA",
101   "AMMO", "LEVEL", "SCORE",
102   "THRUST", "BULLET", "BALL", "BOMBER", "BOMB1", "BOMB2", "SPAWN",
103   "EXPLOSION", "EXPLOSION1", "EXPLOSION2", "EXPLOSION3",
104   "CASTLE", "CANNON", "CANNONA", "CANNONP", "TARGET",
105   "WORM", "BAZOOKA", "XUNUX", "INCASTLE"
106   };
107 
108 struct TIcon {
109   int size;
110   int pixel[64][64];
111   };
112 
113 struct TDisplayIcon {
114   TIcon i;
115   void loadFrom(FILE *f);
116   void fillWith(const char *chars, int size);
117   void fillTile(TDisplayIcon &orig, int size);
118   void gradFill(int x0, int y0, int x1, int y1, int c0, int c1);
119   void gradBall(int x0, int y0, int x1, int y1, int c0, int c1);
120   void drawLines(int x0, int y0, int x1, int y1, int color, int type);
121   };
122 
123 struct TPlayerIcon {
124   TIcon i;
125   int color;
126   void drawAt(int x, int y);
127   void drawAtFlipped(int x, int y);
128   void assignColor(int c);
drawAtCenteredTPlayerIcon129   void drawAtCentered(int x, int y) { drawAt(x-i.size/2, y-i.size/2); }
drawAtCenteredFlippedTPlayerIcon130   void drawAtCenteredFlipped(int x, int y) { drawAtFlipped(x-i.size/2, y-i.size/2); }
131   void drawAtRotated(int x, int y, int rx, int ry);
132   };
133 
134 struct TKeypress {
135   int32 time;
136   int8 pressed, mx, my, key;
137   int32 player; // int32 because also used for color
138   };
139 
size(vector<T> v)140 template<class T> static inline int size(vector<T> v) {return v.size();}
141 
142 enum TGameType {gLocal, gHost, gClient};
143 
144 enum TWorldType {
145   wtEmpty,
146   wtCavern,
147   wtSwissCheese,
148   wtConstruction,
149   wtFrame,
150   wtGrid,
151   wtRuins,
152   wtWall,
153   wtLoad,
154   wtLastWorldType
155   };
156 
157 static const int numWorldTypes = int(wtLastWorldType);
158 
159 static char* worldNames[numWorldTypes] = {
160   "EMPTY", "CAVERN", "SWISS CHEESE", "CONSTRUCTION", "FRAME", "GRID", "RUINS", "WALL", "SAVED MAP"
161   };
162 
163 enum TBackground {
164   bgBlack,
165   bgPlasma,
166   bgGradient,
167   bgGrid,
168   bgGray
169   };
170 
171 enum TGraphicsType {
172   gtGradient,
173   gtRetro,
174   gtLines,
175   gtASCII
176   };
177 
178 static char* bgNames[5] = {"BLACK", "PLASMA", "GRADIENT", "GRID", "GRAY"};
179 
180 static char* gtNames[3] = {"GRADIENT", "RETRO", "LINES"};
181 
182 struct TEntityConfig {
183   int32 initSpeed;
184   int32 speedBonus;
185   int32 maxSpeed;
186   int32 initAmmo;
187   int32 bonusAmmo;
188   int32 ammoPerShoot;
189   };
190 
191 struct TConfig {
192   TGameType gt;
193   string server;
194   string mapname;
195   int  port;
196   int  res;
197   int  pctX, pctY, scorelines;
198   int  resX;
199   int  resY;
200   int  initialWorld;
201   int  initBonus;
202 
203   int  background;
204   int  graphicsType;
205 
206   bool fs;
207   bool centered;
208 
209   string err;
210   bool ok;
211   };
212 
213 struct TGameConfig {
214   TEntityConfig ec[9];
215 
216   int32 ballSpeed, bombInitRange, bombBonusRange, castleInitEnergy, castleRotSpeed, castleRegenSpeed, castlePowerBase,
217     ammoPerCannon, utetrisMinLength, initFuel, bonusFuel, thrustAcc, fuelUseSpeed, wormWalkSpeed, wormFlySpeed,
218     ninjaRopeLength, ninjaPullSpeed;
219 
220   bool
221     ballsTakeBonuses,
222     regenerateLevel, regenerateScore, regenerateAmmo, regenerateDestroyed,
223 
224     bulletsKillBalls, cannonsKillBalls, explosionsDestroyBalls, ballsDestroyXunux, ballsDestroyWalls,
225     xunuxKillsSnake, xunuxKillsThruster, xunuxKillsXunux, xunuxAttacksXunux;
226 
regenerateTGameConfig227   bool regenerate(CellType c) {
228     if(c == cBonusLevel) return regenerateLevel;
229     if(c == cBonusScore) return regenerateScore;
230     if(c == cBonusAmmo ) return regenerateAmmo;
231     }
232   };
233 
234 TConfig c;
235 TGameConfig gc;
236 
237 struct TLocalPlayer {
238   int index;   // index in the player table
239   int keys[8]; // keys for this player
240   int color;
241   };
242 
243 struct TDisplay {
244 
245   TDisplayIcon icons[numIcons];
246 
247   Mix_Chunk
248     *sndBirth, *sndDeath,
249     *sndBlue, *sndGreen, *sndRed,
250     *sndShoot, *sndHit, *sndPlace;
251 
252   SDL_Surface *surface;
253   TTF_Font *font;
254   int sizeX;
255   int sizeY;
256   int ofsX;
257   int ofsY;
258   int Res;
259   bool stop;
260 
261   int *bground; // background image
262 
263   int interpretPixel(char ch);
264 
265   int delta; // time difference
266 
267   int getCurrentTime();
268   void setCurrentTime(int val);
269 
270   void init();
271 
272   void setMode();
273 
274   void initForGame();
275 
276   void initBackground();
277 
278   void loop();
279 
280   void draw();
281 
282   void putpix(int x, int y, int c);
283 
284   void playSoundAt(Mix_Chunk *sound, int x, int y);
285 
286   void addKeypress(int key, bool type);
287   void addMouseEvent(int x, int y, int type, int button);
288 
289   void putText(int x, int y, int color, const char *text, int align);
290 
291   void menuLoop();
292   void menuKey(int key);
293   void menuDraw();
294 
295   int menupos;
296 
297   void genBGround(int x0, int y0, int x1, int y1, int sy);
298   };
299 
300 struct TException {
301   string msg;
302   int data;
303   string ds;
304   TException(string m, int d=0, string s="") {msg=m; data=d; ds=s;}
305   };
306 
307 struct TPlayer {
308   TPlayerIcon icons[numIcons];
309   int8 index;
310   int8 editing, charid, editid;
311   int16 lives, frags;
312   int32 score, level, ammo, typeval;
313   int16 killer;   // who killed us - used by Xunux
314   char *getTypeName();
315   int32 color; // color used
316   bool key[8]; // keys pressed
localDrawTPlayer317   void localDraw() {}
318   void init(int c);
useAmmoTPlayer319   bool useAmmo(int qty)
320     {if(ammo < qty) return false; ammo -= qty; return true;}
ecTPlayer321   TEntityConfig& ec() { return gc.ec[charid]; }
useAmmoTPlayer322   bool useAmmo() { useAmmo(ec().ammoPerShoot); }
gainAmmoTPlayer323   void gainAmmo() { ammo += ec().bonusAmmo; }
324   void save(TBuffer& b);
325   void load(TBuffer& b);
326   void createIcons();
327   };
328 
329 struct TPlayObject {
330   public:
331   int8 owner;
332   int32 time;
getTimeTPlayObject333   int getTime() {return time;}
~TPlayObjectTPlayObject334   virtual ~TPlayObject () {}
reactToKeyTPlayObject335   virtual void reactToKey(PlayerKey pk, bool pressed) {}
336   virtual void reactToKey(TKeypress& k);
drawTPlayObject337   virtual void draw() {}
goTPlayObject338   virtual void go() {}
339   virtual void pausedGo();
delayTPlayObject340   virtual void delay(int t) { time += t; } // remove for non-paused objects
341   TPlayer *ow();
342 
ecTPlayObject343   struct TEntityConfig& ec() { return ow()->ec(); }
344   int spd();
scoreGainTPlayObject345   int scoreGain() { return (10+ow()->level)*(10+ow()->level)/10; }
bulletSpeedTPlayObject346   int bulletSpeed() { return 50 + ow()->level/4; }
347   virtual void save(TBuffer& b) = 0;
348 
349   // these methods are supposed to check whether the two collide
reactToBulletTPlayObject350   virtual bool reactToBullet(struct OBullet* bullet) {return false;}
351   // return true if the bullet is to disappear
reactToPadTPlayObject352   virtual bool reactToPad(struct OPad* pad) {return false;}
353   // return true if it kills the pad (reactToPad destroys pad object)
reactToThrusterTPlayObject354   virtual bool reactToThruster(struct OThruster* bullet) {return false;}
355   // return true if it kills the thruster (react destroy thuster)
smashedByBallTPlayObject356   virtual bool smashedByBall(struct OBall* ball) {return false;}
357   // return true if it changes the ball's direction
reactToCannonTPlayObject358   virtual void reactToCannon(struct OCannonball* ball) {}
359   // return true if it changes the ball's direction
destroyBallsTPlayObject360   virtual void destroyBalls() { }
361   // react to 'no balls' command
catchesRopeTPlayObject362   virtual bool catchesRope(int rx, int ry) {return false;}
363   // does ninja rope at (rx,ry) hook to it?
pullRopeTPlayObject364   virtual void pullRope(struct OWorm *worm, int ddx, int ddy) {}
365   // pull the ninja rope at (x,y)
366 
367   void killedBy(int player);
368   // player killed me -- this deletes the object and scores a frag
369   };
370 
371 struct TPlayground {
372   int32 time;
373   int32 kqpos;
374   bool  paused;
375 
376   int64 seed;
377   int rand();
378 
379   int16 sizeX, sizeY;
380   CellType map[MAXY][MAXX];
381   char owner[MAXY][MAXX];
382 
mapSetTPlayground383   void mapSet(int x, int y, CellType c, char o) {
384     map[y][x] = c;
385     owner[y][x] = o;
386     }
387 
388   vector<TPlayer*> pl;
389   vector<TPlayObject*> objects;
390 
391   void upTime(int newTime);
392 
393   void cleanup();
394   void init(int sx, int sy);
395   void generate();
396   void saveMap();
397   void destroyBalls();
398 
399   int addPlayer(TPlayer* p);
400 
401   void deleteObject(TPlayObject *obj);
402 
403   void save(TBuffer& b);
404   void load(TBuffer& b);
405   };
406 
407 char *charnames[10] = {
408   "SNAKE",
409   "UTRON",
410   "UTETRIS",
411   "THRUSTER",
412   "BOMBER",
413   "CASTLE",
414   "WORM",
415   "PAD",
416   "XUNUX",
417   "Ball"
418   };
419 
420 char *editnames[13] = {
421   "-neutral ball-",
422   "-break wall-",
423   "-perma wall-",
424   "-clear-",
425   "-cannon-",
426   "-bonus ammo-",
427   "-bonus level-",
428   "-bonus other-",
429   "generate [F7]",
430   "no balls [F8]",
431   "save map [F2]",
432   "pause game [F4]",
433   "quit game [ESC]"
434   };
435 
436 #define tnSNAKE    0
437 #define tnUTRON    1
438 #define tnUTETRIS  2
439 #define tnTHRUSTER 3
440 #define tnBOMBER   4
441 #define tnCASTLE   5
442 #define tnWORM     6
443 #define tnPAD      7
444 #define tnXUNUX    8
445 
446 #define KQSIZE 32768
447 
448 TDisplay d;
449 TPlayground g;
450 vector<TLocalPlayer> lps;
451 
452 TKeypress kqueue[KQSIZE];
453 int kqend;
454 
455 void addKeyToQueue(TKeypress& kp);
456 
457 void startGame();
458 void dataTransfer();
459 void broadcastKey(TKeypress& kp);
460 
461