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