1 /*=============================================================================
2 Blobby Volley 2
3 Copyright (C) 2006 Jonathan Sieber (jonathan_sieber@yahoo.de)
4 Copyright (C) 2006 Daniel Knobe (daniel-knobe@web.de)
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 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 =============================================================================*/
20
21 /* header include */
22 #include "GameLogic.h"
23
24 /* includes */
25 #include <cassert>
26 #include <cmath>
27 #include <iostream>
28
29 extern "C"
30 {
31 #include "lua/lua.h"
32 #include "lua/lauxlib.h"
33 #include "lua/lualib.h"
34 }
35
36 #include "FileRead.h"
37 #include "GameLogicState.h"
38 #include "DuelMatch.h"
39 #include "GameConstants.h"
40 #include "IUserConfigReader.h"
41 #include "IScriptableComponent.h"
42 #include "PlayerInput.h"
43
44
lua_toint(lua_State * state,int index)45 int lua_toint(lua_State* state, int index)
46 {
47 double value = lua_tonumber(state, index);
48 return int(value + (value > 0 ? 0.5 : -0.5));
49 }
50
51
52 /* implementation */
53
54 /// how many steps must pass until the next hit can happen
55 const int SQUISH_TOLERANCE = 11;
56
57 const std::string FALLBACK_RULES_NAME = "__FALLBACK__";
58 const std::string DUMMY_RULES_NAME = "__DUMMY__";
59
60
IGameLogic()61 IGameLogic::IGameLogic()
62 : mScoreToWin(IUserConfigReader::createUserConfigReader("config.xml")->getInteger("scoretowin"))
63 , mSquishWall(0)
64 , mSquishGround(0)
65 , mLastError(NO_PLAYER)
66 , mServingPlayer(NO_PLAYER)
67 , mIsBallValid(true)
68 , mIsGameRunning(false)
69 , mWinningPlayer(NO_PLAYER)
70 {
71 // init clock
72 clock.reset();
73 clock.start();
74 mScores[LEFT_PLAYER] = 0;
75 mScores[RIGHT_PLAYER] = 0;
76 mTouches[LEFT_PLAYER] = 0;
77 mTouches[RIGHT_PLAYER] = 0;
78 mSquish[LEFT_PLAYER] = 0;
79 mSquish[RIGHT_PLAYER] = 0;
80 }
81
~IGameLogic()82 IGameLogic::~IGameLogic()
83 {
84 // nothing to do
85 }
86
getTouches(PlayerSide side) const87 int IGameLogic::getTouches(PlayerSide side) const
88 {
89 return mTouches[side2index(side)];
90 }
91
getScore(PlayerSide side) const92 int IGameLogic::getScore(PlayerSide side) const
93 {
94 return mScores[side2index(side)];
95 }
96
setScore(PlayerSide side,int score)97 void IGameLogic::setScore(PlayerSide side, int score)
98 {
99 mScores[side2index(side)] = score;
100 }
101
102
getScoreToWin() const103 int IGameLogic::getScoreToWin() const
104 {
105 return mScoreToWin;
106 }
107
getServingPlayer() const108 PlayerSide IGameLogic::getServingPlayer() const
109 {
110 return mServingPlayer;
111 }
112
setServingPlayer(PlayerSide side)113 void IGameLogic::setServingPlayer(PlayerSide side)
114 {
115 mServingPlayer = side;
116 }
117
getWinningPlayer() const118 PlayerSide IGameLogic::getWinningPlayer() const
119 {
120 return mWinningPlayer;
121 }
122
getClock()123 Clock& IGameLogic::getClock()
124 {
125 return clock;
126 }
127
getLastErrorSide()128 PlayerSide IGameLogic::getLastErrorSide()
129 {
130 PlayerSide t = mLastError;
131 mLastError = NO_PLAYER;
132 /// reset mLastError to NO_PLAYER
133 /// why?
134 return t;
135 }
136
getState() const137 GameLogicState IGameLogic::getState() const
138 {
139 GameLogicState gls;
140 gls.leftScore = getScore(LEFT_PLAYER);
141 gls.rightScore = getScore(RIGHT_PLAYER);
142 gls.servingPlayer = getServingPlayer();
143 gls.leftSquish = mSquish[LEFT_PLAYER];
144 gls.rightSquish = mSquish[RIGHT_PLAYER];
145 gls.squishWall = mSquishWall;
146 gls.squishGround = mSquishGround;
147 gls.isGameRunning = mIsGameRunning;
148 gls.isBallValid = mIsBallValid;
149
150 return gls;
151 }
152
setState(GameLogicState gls)153 void IGameLogic::setState(GameLogicState gls)
154 {
155 setScore(LEFT_PLAYER, gls.leftScore);
156 setScore(RIGHT_PLAYER, gls.rightScore);
157 setServingPlayer(gls.servingPlayer);
158 mSquish[LEFT_PLAYER] = gls.leftSquish;
159 mSquish[RIGHT_PLAYER] = gls.rightSquish;
160 mSquishWall = gls.squishWall;
161 mSquishGround = gls.squishGround;
162 mIsGameRunning = gls.isGameRunning;
163 mIsBallValid = gls.isBallValid;
164 }
165
166 // -------------------------------------------------------------------------------------------------
167 // Event Handlers
168 // -------------------------------------------------------------------------------------------------
step()169 void IGameLogic::step()
170 {
171 clock.step();
172
173 if(clock.isRunning())
174 {
175 --mSquish[0];
176 --mSquish[1];
177 --mSquishWall;
178 --mSquishGround;
179
180 OnGameHandler();
181 }
182 }
183
onPause()184 void IGameLogic::onPause()
185 {
186 /// pausing for now only means stopping the clock
187 clock.stop();
188 }
189
onUnPause()190 void IGameLogic::onUnPause()
191 {
192 clock.start();
193 }
194
transformInput(PlayerInput ip,PlayerSide player)195 PlayerInput IGameLogic::transformInput(PlayerInput ip, PlayerSide player)
196 {
197 return handleInput(ip, player);
198 }
199
onServe()200 void IGameLogic::onServe()
201 {
202 mIsBallValid = true;
203 mIsGameRunning = false;
204 }
205
onBallHitsGround(PlayerSide side)206 void IGameLogic::onBallHitsGround(PlayerSide side)
207 {
208 // check if collision valid
209 if(!isGroundCollisionValid())
210 return;
211
212 // otherwise, set the squish value
213 mSquishGround = SQUISH_TOLERANCE;
214
215 mTouches[other_side(side)] = 0;
216
217 OnBallHitsGroundHandler(side);
218 }
219
isBallValid() const220 bool IGameLogic::isBallValid() const
221 {
222 return mIsBallValid;
223 }
224
isGameRunning() const225 bool IGameLogic::isGameRunning() const
226 {
227 return mIsGameRunning;
228 }
229
isCollisionValid(PlayerSide side) const230 bool IGameLogic::isCollisionValid(PlayerSide side) const
231 {
232 // check whether the ball is squished
233 return mSquish[side2index(side)] <= 0;
234 }
235
isGroundCollisionValid() const236 bool IGameLogic::isGroundCollisionValid() const
237 {
238 // check whether the ball is squished
239 return mSquishGround <= 0 && isBallValid();
240 }
241
isWallCollisionValid() const242 bool IGameLogic::isWallCollisionValid() const
243 {
244 // check whether the ball is squished
245 return mSquishWall <= 0 && isBallValid();
246 }
247
onBallHitsPlayer(PlayerSide side)248 void IGameLogic::onBallHitsPlayer(PlayerSide side)
249 {
250 if(!isCollisionValid(side))
251 return;
252
253 // otherwise, set the squish value
254 mSquish[side2index(side)] = SQUISH_TOLERANCE;
255 // now, the other blobby has to accept the new hit!
256 mSquish[side2index(other_side(side))] = 0;
257
258 // set the ball activity
259 mIsGameRunning = true;
260
261 // count the touches
262 mTouches[side2index(side)]++;
263 OnBallHitsPlayerHandler(side);
264
265 // reset other players touches after OnBallHitsPlayerHandler is called, so
266 // we have still access to its old value inside the handler function
267 mTouches[side2index(other_side(side))] = 0;
268 }
269
onBallHitsWall(PlayerSide side)270 void IGameLogic::onBallHitsWall(PlayerSide side)
271 {
272 if(!isWallCollisionValid())
273 return;
274
275 // otherwise, set the squish value
276 mSquishWall = SQUISH_TOLERANCE;
277
278 OnBallHitsWallHandler(side);
279 }
280
onBallHitsNet(PlayerSide side)281 void IGameLogic::onBallHitsNet(PlayerSide side)
282 {
283 if(!isWallCollisionValid())
284 return;
285
286 // otherwise, set the squish value
287 mSquishWall = SQUISH_TOLERANCE;
288
289 OnBallHitsNetHandler(side);
290 }
291
score(PlayerSide side,int amount)292 void IGameLogic::score(PlayerSide side, int amount)
293 {
294 int index = side2index(side);
295 mScores[index] += amount;
296 if (mScores[index] < 0)
297 mScores[index] = 0;
298
299 mWinningPlayer = checkWin();
300 }
301
onError(PlayerSide errorSide,PlayerSide serveSide)302 void IGameLogic::onError(PlayerSide errorSide, PlayerSide serveSide)
303 {
304 mLastError = errorSide;
305 mIsBallValid = false;
306
307 mTouches[0] = 0;
308 mTouches[1] = 0;
309 mSquish[0] = 0;
310 mSquish[1] = 0;
311 mSquishWall = 0;
312 mSquishGround = 0;
313
314 mServingPlayer = serveSide;
315 }
316
317 // -------------------------------------------------------------------------------------------------
318 // Dummy Game Logic
319 // ---------------------
320
321 class DummyGameLogic : public IGameLogic
322 {
323 public:
DummyGameLogic()324 DummyGameLogic()
325 {
326 }
~DummyGameLogic()327 virtual ~DummyGameLogic()
328 {
329
330 }
331
clone() const332 virtual GameLogic clone() const
333 {
334 return GameLogic(new DummyGameLogic());
335 }
336
getSourceFile() const337 virtual std::string getSourceFile() const
338 {
339 return std::string("");
340 }
341
getAuthor() const342 virtual std::string getAuthor() const
343 {
344 return "Blobby Volley 2 Developers";
345 }
346
getTitle() const347 virtual std::string getTitle() const
348 {
349 return DUMMY_RULES_NAME;
350 }
351
352 protected:
353
checkWin() const354 virtual PlayerSide checkWin() const
355 {
356 return NO_PLAYER;
357 }
358
handleInput(PlayerInput ip,PlayerSide player)359 virtual PlayerInput handleInput(PlayerInput ip, PlayerSide player)
360 {
361 return ip;
362 }
363
OnBallHitsPlayerHandler(PlayerSide side)364 virtual void OnBallHitsPlayerHandler(PlayerSide side)
365 {
366 }
367
OnBallHitsWallHandler(PlayerSide side)368 virtual void OnBallHitsWallHandler(PlayerSide side)
369 {
370 }
371
OnBallHitsNetHandler(PlayerSide side)372 virtual void OnBallHitsNetHandler(PlayerSide side)
373 {
374 }
375
OnBallHitsGroundHandler(PlayerSide side)376 virtual void OnBallHitsGroundHandler(PlayerSide side)
377 {
378 }
379
OnGameHandler()380 virtual void OnGameHandler()
381 {
382 }
383 };
384
385
386 // -------------------------------------------------------------------------------------------------
387 // Fallback Game Logic
388 // ---------------------
389
390 class FallbackGameLogic : public DummyGameLogic
391 {
392 public:
FallbackGameLogic()393 FallbackGameLogic()
394 {
395 }
~FallbackGameLogic()396 virtual ~FallbackGameLogic()
397 {
398
399 }
400
clone() const401 virtual GameLogic clone() const
402 {
403 return GameLogic(new FallbackGameLogic());
404 }
405
getTitle() const406 virtual std::string getTitle() const
407 {
408 return FALLBACK_RULES_NAME;
409 }
410
411 protected:
412
checkWin() const413 virtual PlayerSide checkWin() const
414 {
415 int left = getScore(LEFT_PLAYER);
416 int right = getScore(RIGHT_PLAYER);
417 int stw = getScoreToWin();
418 if( left >= stw && left >= right + 2 )
419 {
420 return LEFT_PLAYER;
421 }
422
423 if( right >= stw && right >= left + 2 )
424 {
425 return RIGHT_PLAYER;
426 }
427
428 return NO_PLAYER;
429 }
430
OnBallHitsPlayerHandler(PlayerSide side)431 virtual void OnBallHitsPlayerHandler(PlayerSide side)
432 {
433 if (getTouches(side) > 3)
434 {
435 score( other_side(side), 1 );
436 onError( side, other_side(side) );
437 }
438 }
439
OnBallHitsGroundHandler(PlayerSide side)440 virtual void OnBallHitsGroundHandler(PlayerSide side)
441 {
442 score( other_side(side), 1 );
443 onError( side, other_side(side) );
444 }
445 };
446
447
448 class LuaGameLogic : public FallbackGameLogic, public IScriptableComponent
449 {
450 public:
451 LuaGameLogic(const std::string& file, DuelMatch* match);
452 virtual ~LuaGameLogic();
453
getSourceFile() const454 virtual std::string getSourceFile() const
455 {
456 return mSourceFile;
457 }
458
clone() const459 virtual GameLogic clone() const
460 {
461 lua_getglobal(mState, "__MATCH_POINTER");
462 DuelMatch* match = (DuelMatch*)lua_touserdata(mState, -1);
463 lua_pop(mState, 1);
464 return GameLogic(new LuaGameLogic(mSourceFile, match));
465 }
466
getAuthor() const467 virtual std::string getAuthor() const
468 {
469 return mAuthor;
470 }
471
getTitle() const472 virtual std::string getTitle() const
473 {
474 return mTitle;
475 }
476
477
478 protected:
479
480 virtual PlayerInput handleInput(PlayerInput ip, PlayerSide player);
481 virtual PlayerSide checkWin() const;
482 virtual void OnBallHitsPlayerHandler(PlayerSide side);
483 virtual void OnBallHitsWallHandler(PlayerSide side);
484 virtual void OnBallHitsNetHandler(PlayerSide side);
485 virtual void OnBallHitsGroundHandler(PlayerSide side);
486 virtual void OnGameHandler();
487
488 static LuaGameLogic* getGameLogic(lua_State* state);
489
490 private:
491
492 // lua functions
493 static int luaTouches(lua_State* state);
494 static int luaLaunched(lua_State* state);
495 static int luaBallX(lua_State* state);
496 static int luaBallY(lua_State* state);
497 static int luaBSpeedX(lua_State* state);
498 static int luaBSpeedY(lua_State* state);
499 static int luaPosX(lua_State* state);
500 static int luaPosY(lua_State* state);
501 static int luaSpeedX(lua_State* state);
502 static int luaSpeedY(lua_State* state);
503 static int luaMistake(lua_State* state);
504 static int luaScore(lua_State* state);
505 static int luaGetScore(lua_State* state);
506 static int luaGetOpponent(lua_State* state);
507 static int luaGetServingPlayer(lua_State* state);
508 static int luaGetGameTime(lua_State* state);
509 static int luaIsGameRunning(lua_State* state);
510
511 // lua state
512 std::string mSourceFile;
513
514 std::string mAuthor;
515 std::string mTitle;
516 };
517
518
LuaGameLogic(const std::string & filename,DuelMatch * match)519 LuaGameLogic::LuaGameLogic( const std::string& filename, DuelMatch* match ) : mSourceFile(filename)
520 {
521 lua_pushlightuserdata(mState, this);
522 lua_setglobal(mState, "__GAME_LOGIC_POINTER");
523
524 /// \todo use lua registry instead of globals!
525 lua_pushlightuserdata(mState, match);
526 lua_setglobal(mState, "__MATCH_POINTER");
527 lua_pushnumber(mState, getScoreToWin());
528 lua_setglobal(mState, "SCORE_TO_WIN");
529
530 setGameConstants();
531
532 // add functions
533 luaL_requiref(mState, "math", luaopen_math, 1);
534 lua_register(mState, "touches", luaTouches);
535 lua_register(mState, "launched", luaLaunched);
536 lua_register(mState, "ballx", luaBallX);
537 lua_register(mState, "bally", luaBallY);
538 lua_register(mState, "bspeedx", luaBSpeedX);
539 lua_register(mState, "bspeedy", luaBSpeedY);
540 lua_register(mState, "posx", luaPosX);
541 lua_register(mState, "posy", luaPosY);
542 lua_register(mState, "speedx", luaSpeedX);
543 lua_register(mState, "speedy", luaSpeedY);
544 lua_register(mState, "getScore", luaGetScore);
545 lua_register(mState, "score", luaScore);
546 lua_register(mState, "mistake", luaMistake);
547 lua_register(mState, "opponent", luaGetOpponent);
548 lua_register(mState, "servingplayer", luaGetServingPlayer);
549 lua_register(mState, "time", luaGetGameTime);
550 lua_register(mState, "isgamerunning", luaIsGameRunning);
551
552 // now load script file
553 int error = FileRead::readLuaScript(std::string("rules/") + filename, mState);
554
555 if (error == 0)
556 error = lua_pcall(mState, 0, 6, 0);
557
558 if (error)
559 {
560 std::cerr << "Lua Error: " << lua_tostring(mState, -1);
561 std::cerr << std::endl;
562 ScriptException except;
563 except.luaerror = lua_tostring(mState, -1);
564 throw except;
565 }
566
567 lua_getglobal(mState, "SCORE_TO_WIN");
568 mScoreToWin = lua_toint(mState, -1);
569 lua_pop(mState, 1);
570
571 lua_getglobal(mState, "__AUTHOR__");
572 const char* author = lua_tostring(mState, -1);
573 mAuthor = ( author ? author : "unknown author" );
574 lua_pop(mState, 1);
575
576 lua_getglobal(mState, "__TITLE__");
577 const char* title = lua_tostring(mState, -1);
578 mTitle = ( title ? title : "untitled script" );
579 lua_pop(mState, 1);
580
581 std::cout << "loaded rules "<< getTitle()<< " by " << getAuthor() << " from " << mSourceFile << std::endl;
582 }
583
~LuaGameLogic()584 LuaGameLogic::~LuaGameLogic()
585 {
586 }
587
checkWin() const588 PlayerSide LuaGameLogic::checkWin() const
589 {
590 bool won = false;
591 if (!getLuaFunction("IsWinning"))
592 {
593 return FallbackGameLogic::checkWin();
594 }
595
596 lua_pushnumber(mState, getScore(LEFT_PLAYER) );
597 lua_pushnumber(mState, getScore(RIGHT_PLAYER) );
598 if( lua_pcall(mState, 2, 1, 0) )
599 {
600 std::cerr << "Lua Error: " << lua_tostring(mState, -1);
601 std::cerr << std::endl;
602 };
603
604 won = lua_toboolean(mState, -1);
605 lua_pop(mState, 1);
606
607 if(won)
608 {
609 if( getScore(LEFT_PLAYER) > getScore(RIGHT_PLAYER) )
610 return LEFT_PLAYER;
611
612 if( getScore(LEFT_PLAYER) < getScore(RIGHT_PLAYER) )
613 return RIGHT_PLAYER;
614 }
615
616 return NO_PLAYER;
617 }
618
handleInput(PlayerInput ip,PlayerSide player)619 PlayerInput LuaGameLogic::handleInput(PlayerInput ip, PlayerSide player)
620 {
621 if (!getLuaFunction( "HandleInput" ))
622 {
623 return FallbackGameLogic::handleInput(ip, player);
624 }
625 lua_pushnumber(mState, player);
626 lua_pushboolean(mState, ip.left);
627 lua_pushboolean(mState, ip.right);
628 lua_pushboolean(mState, ip.up);
629 if(lua_pcall(mState, 4, 3, 0))
630 {
631 std::cerr << "Lua Error: " << lua_tostring(mState, -1);
632 std::cerr << std::endl;
633 };
634
635 PlayerInput ret;
636 ret.up = lua_toboolean(mState, -1);
637 ret.right = lua_toboolean(mState, -2);
638 ret.left = lua_toboolean(mState, -3);
639
640 // cleanup stack
641 lua_pop(mState, lua_gettop(mState));
642
643 return ret;
644 }
645
OnBallHitsPlayerHandler(PlayerSide side)646 void LuaGameLogic::OnBallHitsPlayerHandler(PlayerSide side)
647 {
648 if (!getLuaFunction("OnBallHitsPlayer"))
649 {
650 FallbackGameLogic::OnBallHitsPlayerHandler(side);
651 return;
652 }
653 lua_pushnumber(mState, side);
654 if( lua_pcall(mState, 1, 0, 0) )
655 {
656 std::cerr << "Lua Error: " << lua_tostring(mState, -1);
657 std::cerr << std::endl;
658 };
659 }
660
OnBallHitsWallHandler(PlayerSide side)661 void LuaGameLogic::OnBallHitsWallHandler(PlayerSide side)
662 {
663 if (!getLuaFunction("OnBallHitsWall"))
664 {
665 FallbackGameLogic::OnBallHitsWallHandler(side);
666 return;
667 }
668
669 lua_pushnumber(mState, side);
670 if( lua_pcall(mState, 1, 0, 0) )
671 {
672 std::cerr << "Lua Error: " << lua_tostring(mState, -1);
673 std::cerr << std::endl;
674 };
675 }
676
OnBallHitsNetHandler(PlayerSide side)677 void LuaGameLogic::OnBallHitsNetHandler(PlayerSide side)
678 {
679 if (!getLuaFunction( "OnBallHitsNet" ))
680 {
681 FallbackGameLogic::OnBallHitsNetHandler(side);
682 return;
683 }
684
685 lua_pushnumber(mState, side);
686
687 if( lua_pcall(mState, 1, 0, 0) )
688 {
689 std::cerr << "Lua Error: " << lua_tostring(mState, -1);
690 std::cerr << std::endl;
691 };
692 }
693
OnBallHitsGroundHandler(PlayerSide side)694 void LuaGameLogic::OnBallHitsGroundHandler(PlayerSide side)
695 {
696 if (!getLuaFunction( "OnBallHitsGround" ))
697 {
698 FallbackGameLogic::OnBallHitsGroundHandler(side);
699 return;
700 }
701
702 lua_pushnumber(mState, side);
703
704 if( lua_pcall(mState, 1, 0, 0) )
705 {
706 std::cerr << "Lua Error: " << lua_tostring(mState, -1);
707 std::cerr << std::endl;
708 };
709 }
710
OnGameHandler()711 void LuaGameLogic::OnGameHandler()
712 {
713 if (!getLuaFunction( "OnGame" ))
714 {
715 FallbackGameLogic::OnGameHandler();
716 return;
717 }
718 if( lua_pcall(mState, 0, 0, 0) )
719 {
720 std::cerr << "Lua Error: " << lua_tostring(mState, -1);
721 std::cerr << std::endl;
722 };
723 }
724
getGameLogic(lua_State * state)725 LuaGameLogic* LuaGameLogic::getGameLogic(lua_State* state)
726 {
727 lua_getglobal(state, "__GAME_LOGIC_POINTER");
728 LuaGameLogic* gl = (LuaGameLogic*)lua_touserdata(state, -1);
729 lua_pop(state, 1);
730 return gl;
731 }
732
luaTouches(lua_State * state)733 int LuaGameLogic::luaTouches(lua_State* state)
734 {
735 LuaGameLogic* gl = getGameLogic(state);
736
737 PlayerSide side = (PlayerSide)lua_toint(state, -1);
738 lua_pop(state, 1);
739 lua_pushnumber(state, gl->getTouches(side));
740 return 1;
741 }
742
luaLaunched(lua_State * state)743 int LuaGameLogic::luaLaunched(lua_State* state)
744 {
745 lua_getglobal(state, "__MATCH_POINTER");
746 DuelMatch* match = (DuelMatch*)lua_touserdata(state, -1);
747 lua_pop(state, 1);
748
749 PlayerSide side = (PlayerSide)lua_toint(state, -1);
750 lua_pop(state, 1);
751 lua_pushboolean(state, match->getBlobJump(side));
752 return 1;
753 }
754
luaBallX(lua_State * state)755 int LuaGameLogic::luaBallX(lua_State* state)
756 {
757 lua_getglobal(state, "__MATCH_POINTER");
758 DuelMatch* match = (DuelMatch*)lua_touserdata(state, -1);
759 lua_pop(state, 1);
760
761 float pos = match->getBallPosition().x;
762 lua_pushnumber(state, pos);
763 return 1;
764 }
765
luaBallY(lua_State * state)766 int LuaGameLogic::luaBallY(lua_State* state)
767 {
768 lua_getglobal(state, "__MATCH_POINTER");
769 DuelMatch* match = (DuelMatch*)lua_touserdata(state, -1);
770 lua_pop(state, 1);
771
772 float pos = match->getBallPosition().y;
773 lua_pushnumber(state, pos);
774 return 1;
775 }
776
luaBSpeedX(lua_State * state)777 int LuaGameLogic::luaBSpeedX(lua_State* state)
778 {
779 lua_getglobal(state, "__MATCH_POINTER");
780 DuelMatch* match = (DuelMatch*)lua_touserdata(state, -1);
781 lua_pop(state, 1);
782
783 float vel = match->getBallVelocity().x;
784 lua_pushnumber(state, vel);
785 return 1;
786 }
787
luaBSpeedY(lua_State * state)788 int LuaGameLogic::luaBSpeedY(lua_State* state)
789 {
790 lua_getglobal(state, "__MATCH_POINTER");
791 DuelMatch* match = (DuelMatch*)lua_touserdata(state, -1);
792 lua_pop(state, 1);
793
794 float vel = match->getBallVelocity().y;
795 lua_pushnumber(state, vel);
796 return 1;
797 }
798
luaPosX(lua_State * state)799 int LuaGameLogic::luaPosX(lua_State* state)
800 {
801 lua_getglobal(state, "__MATCH_POINTER");
802 DuelMatch* match = (DuelMatch*)lua_touserdata(state, -1);
803 lua_pop(state, 1);
804
805 PlayerSide side = (PlayerSide)lua_toint(state, -1);
806 lua_pop(state, 1);
807 float pos = match->getBlobPosition(side).x;
808 lua_pushnumber(state, pos);
809 return 1;
810 }
811
luaPosY(lua_State * state)812 int LuaGameLogic::luaPosY(lua_State* state)
813 {
814 lua_getglobal(state, "__MATCH_POINTER");
815 DuelMatch* match = (DuelMatch*)lua_touserdata(state, -1);
816 lua_pop(state, 1);
817
818 PlayerSide side = (PlayerSide)lua_toint(state, -1);
819 lua_pop(state, 1);
820 float pos = match->getBlobPosition(side).y;
821 lua_pushnumber(state, pos);
822 return 1;
823 }
824
luaSpeedX(lua_State * state)825 int LuaGameLogic::luaSpeedX(lua_State* state)
826 {
827 lua_getglobal(state, "__MATCH_POINTER");
828 DuelMatch* match = (DuelMatch*)lua_touserdata(state, -1);
829 lua_pop(state, 1);
830
831 PlayerSide side = (PlayerSide)lua_toint(state, -1);
832 lua_pop(state, 1);
833 float pos = match->getBlobVelocity(side).x;
834 lua_pushnumber(state, pos);
835 return 1;
836 }
837
luaSpeedY(lua_State * state)838 int LuaGameLogic::luaSpeedY(lua_State* state)
839 {
840 lua_getglobal(state, "__MATCH_POINTER");
841 DuelMatch* match = (DuelMatch*)lua_touserdata(state, -1);
842 lua_pop(state, 1);
843
844 PlayerSide side = (PlayerSide)lua_toint(state, -1);
845 lua_pop(state, 1);
846 float pos = match->getBlobVelocity(side).y;
847 lua_pushnumber(state, pos);
848 return 1;
849 }
850
luaGetScore(lua_State * state)851 int LuaGameLogic::luaGetScore(lua_State* state)
852 {
853 int pl = lua_toint(state, -1);
854 lua_pop(state, 1);
855 LuaGameLogic* gl = getGameLogic(state);
856
857 lua_pushnumber(state, gl->getScore((PlayerSide)pl));
858 return 1;
859 }
860
luaMistake(lua_State * state)861 int LuaGameLogic::luaMistake(lua_State* state)
862 {
863 int amount = lua_toint(state, -1);
864 lua_pop(state, 1);
865 PlayerSide serveSide = (PlayerSide)lua_toint(state, -1);
866 lua_pop(state, 1);
867 PlayerSide mistakeSide = (PlayerSide)lua_toint(state, -1);
868 lua_pop(state, 1);
869 LuaGameLogic* gl = getGameLogic(state);
870
871 gl->score(other_side(mistakeSide), amount);
872 gl->onError(mistakeSide, serveSide);
873 return 0;
874 }
875
luaScore(lua_State * state)876 int LuaGameLogic::luaScore(lua_State* state)
877 {
878 int amount = lua_toint(state, -1);
879 lua_pop(state, 1);
880 int player = lua_toint(state, -1);
881 lua_pop(state, 1);
882 LuaGameLogic* gl = getGameLogic(state);
883
884 gl->score((PlayerSide)player, amount);
885 return 0;
886 }
887
luaGetOpponent(lua_State * state)888 int LuaGameLogic::luaGetOpponent(lua_State* state)
889 {
890 int pl = lua_toint(state, -1);
891 lua_pop(state, 1);
892 lua_pushnumber(state, other_side((PlayerSide)pl));
893 return 1;
894 }
895
luaGetServingPlayer(lua_State * state)896 int LuaGameLogic::luaGetServingPlayer(lua_State* state)
897 {
898 LuaGameLogic* gl = getGameLogic(state);
899 lua_pushnumber(state, gl->getServingPlayer());
900 return 1;
901 }
902
luaGetGameTime(lua_State * state)903 int LuaGameLogic::luaGetGameTime(lua_State* state)
904 {
905 LuaGameLogic* gl = getGameLogic(state);
906 lua_pushnumber(state, gl->getClock().getTime());
907 return 1;
908 }
909
luaIsGameRunning(lua_State * state)910 int LuaGameLogic::luaIsGameRunning(lua_State* state)
911 {
912 LuaGameLogic* gl = getGameLogic(state);
913 lua_pushboolean(state, gl->isGameRunning());
914 return 1;
915 }
916
createGameLogic()917 GameLogic createGameLogic()
918 {
919 return GameLogic(new DummyGameLogic());
920 }
createGameLogic(const std::string & file,DuelMatch * match)921 GameLogic createGameLogic(const std::string& file, DuelMatch* match)
922 {
923 if(file == DUMMY_RULES_NAME)
924 {
925 return GameLogic(new DummyGameLogic());
926 }
927 else if (file == FALLBACK_RULES_NAME)
928 {
929 return GameLogic(new FallbackGameLogic());
930 }
931
932 try
933 {
934 return GameLogic( new LuaGameLogic(file, match) );
935 }
936 catch( std::exception& exp)
937 {
938 std::cerr << "Script Error: Could not create LuaGameLogic: \n";
939 std::cerr << exp.what() << std::endl;
940 std::cerr << " Using fallback ruleset";
941 std::cerr << std::endl;
942 return GameLogic(new FallbackGameLogic());
943 }
944
945 }
946