OSCR

I think, therefore I hit: EEG parameters predict performance in complex cognitive tasks

Code ↔ Paper

1 match between paragraphs of the paper and lines of its authors' code, computed by the harvester (lexical-v1). Click a colored paragraph or line to see its counterpart.

The 1 match
  1. [1] § Material and methods › Tasks and material › Space Fortress Game ↔ src/game.py, lines 357 to 406 · score 0.64 · destroyed fortresses, destroyed mines, capturing bonuses, deaths, graphics, shots · Report a mismatch

Paper

Loaded from Europe PMC by your browser; OSCR does not store it: doi.org · Europe PMC

The paper is loaded when this pane is shown.

The authors' code

Python · 1,534 lines · 78 KB · no license · 1 match

  1. from __future__ import division
  2. import numpy as np
  3. from twisted.internet import reactor
  4. from twisted.internet.task import LoopingCall
  5. import os, sys, math, copy, time, datetime, pkg_resources
  6. from random import randrange, choice
  7. import platform as plat
  8. os.environ['SDL_VIDEO_WINDOW_POS'] = 'center'
  9. from OpenGL.GL import *
  10. from OpenGL.GLU import *
  11. import pygame
  12. from pygame.locals import *
  13. import pygl2d
  14. from pygl2d.display import scissor_box, subspace
  15. from gameevent import GameEvent, GameEventList
  16. from frame import Frame
  17. from score import Score
  18. from sound import Sound
  19. from timer import Timer
  20. from hexagon import Hex
  21. from mine import Mine, MineList
  22. from missile import MissileList
  23. from shell import ShellList
  24. from ship import Ship
  25. from bonus import Bonus
  26. from fortress import Fortress
  27. import defaults
  28. get_time = time.time
  29. if plat.system() == 'Windows':
  30. get_time = time.clock
  31. def get_time_ms(): return get_time() * 1000
  32. from version import __version__
  33. def get_psf_version_string():
  34. return "Space Fortress 5"
  35. def get_default_logdir():
  36. _home = os.environ.get('HOME', '/')
  37. if plat.system() == 'Windows':
  38. logdir = os.path.join(os.environ['USERPROFILE'], 'My Documents', 'Spacefortress')
  39. elif plat.system() == 'Linux' or plat.system() == 'Darwin':
  40. logdir = os.path.join(_home, 'Documents', 'Spacefortress')
  41. else:
  42. logdir = os.path.join(_home, 'Spacefortress')
  43. return logdir
  44. release_build = False
  45. class Game(object):
  46. """Main game application"""
  47. def __init__(self):
  48. super(Game, self).__init__()
  49. self.ret = 1
  50. self.reactor = reactor
  51. self.STATE_UNKNOWN = -1
  52. self.STATE_CALIBRATE = 0
  53. self.STATE_INTRO = 1
  54. self.STATE_SETUP = 2
  55. self.STATE_GAMENO = 3
  56. self.STATE_SETUP_IFF = 4
  57. self.STATE_IFF = 5
  58. self.STATE_PREPARE = 6
  59. self.STATE_PLAY = 7
  60. self.STATE_PAUSED = 8
  61. self.STATE_SCORES = 9
  62. self.STATE_DONE = 10
  63. self.state = self.STATE_INTRO
  64. self.ship = None
  65. self.bonus = None
  66. self.score = None
  67. self.fortress = None
  68. self.missile_list = None
  69. self.shell_list = None
  70. self.current_game = 0
  71. self.flight2 = 0
  72. self.mine2 = 0
  73. self.fps = 30
  74. self.header = {}
  75. self.bonus_captured = False
  76. self.modifier = pygame.KMOD_CTRL
  77. if plat.system() == 'Darwin':
  78. self.modifier = pygame.KMOD_META
  79. self.gameevents = GameEventList(self)
  80. self.plugins = {}
  81. #self.plugins = defaults.load_plugins(self, pkg_resources.resource_stream(__name__, 'plugins'), self.plugins)
  82. self.plugins = defaults.load_plugins(self, defaults.get_plugin_home(), self.plugins)
  83. for name in self.plugins:
  84. if hasattr(self.plugins[name], 'eventCallback'):
  85. self.gameevents.addCallback(self.plugins[name].eventCallback)
  86. self.gameevents.add("game", "version", __version__, type='EVENT_SYSTEM')
  87. self.config = defaults.get_config()
  88. if os.path.isfile('config.json'):
  89. self.config.set_user_file('config.json')
  90. else:
  91. self.config.set_user_file(defaults.get_user_file())
  92. self.gameevents.add("config", "load", "defaults", type='EVENT_SYSTEM')
  93. self.config.update_from_user_file()
  94. self.gameevents.add("config", "load", "user", type='EVENT_SYSTEM')
  95. for name in self.plugins:
  96. if hasattr(self.plugins[name], "ready"):
  97. self.plugins[name].ready()
  98. pygame.display.init()
  99. pygame.font.init()
  100. pygame.event.set_blocked((pygame.MOUSEMOTION, pygame.MOUSEBUTTONUP, pygame.MOUSEBUTTONDOWN))
  101. mode_list = pygame.display.list_modes()
  102. if self.config['Display']['display_mode'] == 'Windowed':
  103. if self.config['Display']['screen_width'] > 0 and self.config['Display']['screen_height'] > 0:
  104. best_mode = (self.config['Display']['screen_width'], self.config['Display']['screen_height'])
  105. else:
  106. for mode in mode_list:
  107. tmp = mode[0] / 2
  108. for m in mode_list:
  109. if tmp == m[0]:
  110. mode_list.remove(mode)
  111. break
  112. best_mode = mode_list[1]
  113. else:
  114. if self.config['Display']['display_mode'] == 'Current':
  115. info = pygame.display.Info()
  116. best_mode = (info.current_w, info.current_h)
  117. else:
  118. best_mode = mode_list[0]
  119. self.SCREEN_WIDTH = best_mode[0]
  120. self.SCREEN_HEIGHT = best_mode[1]
  121. self.screen_size = (self.SCREEN_WIDTH, self.SCREEN_HEIGHT)
  122. if self.config['Logging']['logging']:
  123. d = datetime.datetime.now().timetuple()
  124. base = "SpaceFortress-%s_%s_%d-%d-%d_%d-%d-%d" % (__version__, self.config['General']['id'], d[0], d[1], d[2], d[3], d[4], d[5])
  125. logdir = self.config['Logging']['logdir']
  126. if len(logdir.strip()) == 0:
  127. logdir = get_default_logdir()
  128. if not os.path.exists(logdir):
  129. os.makedirs(logdir)
  130. self.log_basename = os.path.join(logdir, base)
  131. self.gameevents.add("log", "basename", "ready", type='EVENT_SYSTEM')
  132. self.log_filename = "%s.txt.incomplete" % (self.log_basename)
  133. self.log = open(self.log_filename, "w")
  134. self.log_header = ["event_type", "system_time", "game_time",
  135. "current_game", "eid", "e1", "e2", "e3", "foes", "ship_alive",
  136. "ship_health", "ship_x", "ship_y", "smod", "dmod", "ship_vel_x",
  137. "ship_vel_y", "ship_orientation", "distance", "mine_no", "mine_id",
  138. "mine", "fortress_alive", "fortress_x", "fortress_y",
  139. "fortress_orientation", "missile", "shell", "bonus_no",
  140. "bonus_prev", "bonus_cur", "bonus_cur_x", "bonus_cur_y"]
  141. if self.config['General']['bonus_system'] == "AX-CPT":
  142. self.log_header.append('bonus_isi')
  143. self.log_header = self.log_header + ["score_pnts", "score_cntrl", "score_vlcty", "score_vlner", "score_iff",
  144. "score_intrvl", "score_speed", "score_shots", "score_flight", "score_flight2",
  145. "score_fortress", "score_mine", "score_mine2", "score_bonus", "thrust_key",
  146. "left_key", "right_key", "fire_key", "iff_key", "shots_key", "pnts_key"]
  147. for name in self.plugins:
  148. if hasattr(self.plugins[name], "logHeader"):
  149. self.log_header = self.log_header + self.plugins[name].logHeader()
  150. self.log.write("\t".join(self.log_header) + "\n")
  151. self.gameevents.add("log", "header", "ready", log=False, type='EVENT_SYSTEM')
  152. self.gameevents.add("log", "version", "8", type='EVENT_SYSTEM')
  153. self.gameevents.add("config", "running", str(self.config), type='EVENT_SYSTEM')
  154. pygame.mouse.set_visible(False)
  155. self.set_aspect_ratio()
  156. os.environ['SDL_VIDEO_WINDOW_POS'] = str(int(mode_list[0][0] / 2 - self.SCREEN_WIDTH / 2)) + "," + str(int(mode_list[0][1] / 2 - self.SCREEN_HEIGHT / 2))
  157. if self.config['General']['next_gen']:
  158. self.WORLD_WIDTH = int((710 + 57) * self.aspect_ratio)
  159. self.WORLD_HEIGHT = int((626 + 57) * self.aspect_ratio)
  160. else:
  161. self.WORLD_WIDTH = int(710 * self.aspect_ratio)
  162. self.WORLD_HEIGHT = int(626 * self.aspect_ratio)
  163. self.linewidth = self.config['Display']['linewidth']
  164. self.stars = []
  165. self.kp_space = self.linewidth
  166. self.kp_right = self.linewidth
  167. self.kp_left = self.linewidth
  168. self.kp_thrust = self.linewidth
  169. self.kp_iff = self.linewidth
  170. self.kp_shots = self.linewidth
  171. self.kp_points = self.linewidth
  172. self.fh = int(self.SCREEN_HEIGHT / 72)
  173. self.fp = pkg_resources.resource_stream('resources', 'fonts/freesansbold.ttf')
  174. self.font1 = pygame.font.Font(self.fp, int(self.SCREEN_HEIGHT / 10))
  175. self.fp.seek(0)
  176. self.font2 = pygame.font.Font(self.fp, self.fh)
  177. self.fp.seek(0)
  178. self.f = pygame.font.Font(self.fp, int(14 * self.aspect_ratio))
  179. self.fp.seek(0)
  180. self.f6 = pygame.font.Font(self.fp, int(12 * self.aspect_ratio))
  181. self.fp.seek(0)
  182. self.f24 = pygame.font.Font(self.fp, int(20 * self.aspect_ratio))
  183. self.fp.seek(0)
  184. self.f28 = pygame.font.Font(self.fp, int(28 * self.aspect_ratio))
  185. self.fp.seek(0)
  186. self.f96 = pygame.font.Font(self.fp, int(72 * self.aspect_ratio))
  187. self.fp.seek(0)
  188. self.f36 = pygame.font.Font(self.fp, int(36 * self.aspect_ratio))
  189. self.joystick = None
  190. if self.config['Joystick']['use_joystick']:
  191. pygame.joystick.init()
  192. self.joystick = pygame.joystick.Joystick(self.config['Joystick']['joystick_id'])
  193. self.joystick.init()
  194. self.fire_button = self.config['Joystick']['fire_button']
  195. self.IFF_button = self.config['Joystick']['iff_button']
  196. self.shots_button = self.config['Joystick']['shots_button']
  197. self.pnts_button = self.config['Joystick']['pnts_button']
  198. self.thrust_key = eval("pygame.K_%s" % self.config['Keybindings']['thrust_key'])
  199. self.left_turn_key = eval("pygame.K_%s" % self.config['Keybindings']['left_turn_key'])
  200. self.right_turn_key = eval("pygame.K_%s" % self.config['Keybindings']['right_turn_key'])
  201. self.fire_key = eval("pygame.K_%s" % self.config['Keybindings']['fire_key'])
  202. self.IFF_key = eval("pygame.K_%s" % self.config['Keybindings']['IFF_key'])
  203. self.shots_key = eval("pygame.K_%s" % self.config['Keybindings']['shots_key'])
  204. self.pnts_key = eval("pygame.K_%s" % self.config['Keybindings']['pnts_key'])
  205. self.pause_key = eval("pygame.K_%s" % self.config['Keybindings']['pause_key'])
  206. if self.config['General']['sound']:
  207. pygame.mixer.init()
  208. pygame.mixer.set_num_channels(32)
  209. self.snd_shell_fired = Sound(self, pkg_resources.resource_stream("resources", "sounds/shellfired.wav"))
  210. self.snd_missile_fired = Sound(self, pkg_resources.resource_stream("resources", "sounds/missilefired.wav"))
  211. self.snd_explosion = Sound(self, pkg_resources.resource_stream("resources", "sounds/expfort.wav"))
  212. self.snd_collision = Sound(self, pkg_resources.resource_stream("resources", "sounds/collision.wav"))
  213. self.snd_vlner_reset = Sound(self, pkg_resources.resource_stream("resources", "sounds/vulnerzeroed.wav"))
  214. self.snd_bonus_success = Sound(self, pkg_resources.resource_stream("resources", "sounds/bonus_success.wav"))
  215. self.snd_bonus_fail = Sound(self, pkg_resources.resource_stream("resources", "sounds/bonus_fail.wav"))
  216. self.snd_empty = Sound(self, pkg_resources.resource_stream("resources", "sounds/emptychamber.wav"))
  217. if self.config['Display']['display_mode'] == 'Fullscreen' or self.config['Display']['display_mode'] == 'Current':
  218. self.screen = pygl2d.display.set_mode((self.SCREEN_WIDTH, self.SCREEN_HEIGHT), pygame.FULLSCREEN | pygame.DOUBLEBUF)
  219. elif self.config['Display']['display_mode'] == 'Fake Fullscreen':
  220. self.screen = pygl2d.display.set_mode((self.SCREEN_WIDTH, self.SCREEN_HEIGHT), pygame.NOFRAME | pygame.DOUBLEBUF)
  221. else:
  222. self.screen = pygl2d.display.set_mode((self.SCREEN_WIDTH, self.SCREEN_HEIGHT), pygame.DOUBLEBUF)
  223. self.screen_rect = self.screen.get_rect()
  224. self.gameevents.add("display", 'setmode', (self.SCREEN_WIDTH, self.SCREEN_HEIGHT, self.aspect_ratio), type='EVENT_SYSTEM')
  225. self.gametimer = Timer(get_time_ms)
  226. self.flighttimer = Timer(self.gametimer.elapsed)
  227. self.frame = Frame(self)
  228. self.score = Score(self)
  229. self.gameevents.add("score1", self.score.scores_locations[0][0], self.score.scores_locations[0][1], type='EVENT_SYSTEM')
  230. self.gameevents.add("score2", self.score.scores_locations[1][0], self.score.scores_locations[1][1], type='EVENT_SYSTEM')
  231. self.gameevents.add("score3", self.score.scores_locations[2][0], self.score.scores_locations[2][1], type='EVENT_SYSTEM')
  232. self.gameevents.add("score4", self.score.scores_locations[3][0], self.score.scores_locations[3][1], type='EVENT_SYSTEM')
  233. self.gameevents.add("score5", self.score.scores_locations[4][0], self.score.scores_locations[4][1], type='EVENT_SYSTEM')
  234. self.gameevents.add("score6", self.score.scores_locations[5][0], self.score.scores_locations[5][1], type='EVENT_SYSTEM')
  235. self.gameevents.add("score7", self.score.scores_locations[6][0], self.score.scores_locations[6][1], type='EVENT_SYSTEM')
  236. self.gameevents.add("score8", self.score.scores_locations[7][0], self.score.scores_locations[7][1], type='EVENT_SYSTEM')
  237. if self.config['Graphics']['fancy']:
  238. self.explosion = pygl2d.image.Image(pkg_resources.resource_stream("resources", 'gfx/exp2.png'))
  239. self.explosion_rect = self.explosion.get_rect()
  240. self.explosion.scale(182 * self.aspect_ratio / 344)
  241. self.explosion.colorize(255.0, 255.0, 255.0, 204)
  242. self.explosion_small = pygl2d.image.Image(pkg_resources.resource_stream("resources", 'gfx/exp3.png'))
  243. self.explosion_small_rect = self.explosion_small.get_rect()
  244. self.explosion_small.scale(70 * self.aspect_ratio / 85)
  245. self.explosion_small.colorize(255.0, 255.0, 255.0, 204)
  246. else:
  247. self.explosion = pygl2d.image.Image(pkg_resources.resource_stream("resources", 'gfx/exp.png'))
  248. self.explosion_rect = self.explosion.get_rect()
  249. self.explosion_small = pygl2d.image.Image(pkg_resources.resource_stream("resources", 'gfx/exp.png'))
  250. self.explosion_small_rect = self.explosion_small.get_rect()
  251. self.world = pygame.rect.Rect(0, 0, self.WORLD_WIDTH, self.WORLD_HEIGHT)
  252. self.world.center = (self.SCREEN_WIDTH / 2, self.SCREEN_HEIGHT / 2)
  253. if not self.config['Score']['new_scoring_pos']:
  254. self.world.top = 5 * self.aspect_ratio
  255. else:
  256. self.world.top = 70 * self.aspect_ratio
  257. self.bighex = Hex(self, self.config['Hexagon']['big_hex'])
  258. self.smallhex = Hex(self, self.config['Hexagon']['small_hex'])
  259. if self.config['Mine']['mine_exists']:
  260. self.mine_exists = True
  261. else:
  262. self.mine_exists = False
  263. self.mine_list = MineList(self)
  264. self.dmod = -1
  265. self.smod = -1
  266. self.intro_title = pygl2d.font.RenderText(get_psf_version_string(), (255, 200, 100), self.font1)
  267. self.intro_title_rect = self.intro_title.get_rect()
  268. self.intro_title_rect.center = (self.SCREEN_WIDTH / 2, self.SCREEN_HEIGHT / 5)
  269. self.intro_vers = pygl2d.font.RenderText('Version: %s' % (__version__), (255, 200, 100), self.font2)
  270. self.intro_vers_rect = self.intro_vers.get_rect()
  271. self.intro_vers_rect.center = (self.SCREEN_WIDTH / 2, 4 * self.SCREEN_HEIGHT / 5 - self.fh / 2 - 2)
  272. self.intro_copy = pygl2d.font.RenderText('Copyright \xa92011 CogWorks Laboratory, Rensselaer Polytechnic Institute', (255, 200, 100), self.font2)
  273. self.intro_copy_rect = self.intro_copy.get_rect()
  274. self.intro_copy_rect.center = (self.SCREEN_WIDTH / 2, 4 * self.SCREEN_HEIGHT / 5 + self.fh / 2 + 2)
  275. self.intro_logo = pygl2d.image.Image(pkg_resources.resource_stream("resources", 'gfx/psf5.png'))
  276. self.intro_logo_rect = self.intro_logo.get_rect()
  277. self.intro_logo_rect.center = (self.SCREEN_WIDTH / 2, self.SCREEN_HEIGHT / 2)
  278. self.intro_logo.scale(.4 * self.SCREEN_HEIGHT / 128)
  279. self.pause = pygl2d.font.RenderText("Paused!", (255, 255, 255), self.f96)
  280. self.pause_rect = self.pause.get_rect()
  281. self.pause_rect.center = (self.SCREEN_WIDTH / 2, self.SCREEN_HEIGHT / 2)
  282. self.happy = pygl2d.image.load_xbm(pkg_resources.resource_stream("resources", "gfx/fill1.xbm"))
  283. self.gameevents.add("session", "ready", type='EVENT_SYSTEM')
  284. def set_aspect_ratio(self):
  285. self.aspect_ratio = self.SCREEN_HEIGHT / 768
  286. xover = self.SCREEN_WIDTH + 2 * (495 * self.aspect_ratio - self.SCREEN_WIDTH / 2)
  287. if xover > self.SCREEN_WIDTH:
  288. self.aspect_ratio = self.SCREEN_WIDTH / 1024
  289. def setup_world(self):
  290. """initializes gameplay"""
  291. self.gameevents.add("game", "setup", type='EVENT_SYSTEM')
  292. self.missile_list = MissileList(self)
  293. self.shell_list = ShellList(self)
  294. self.ship = Ship(self)
  295. self.gametimer.reset()
  296. if self.config['Fortress']['fortress_exists']:
  297. self.fortress = Fortress(self)
  298. self.fortress_exists = True
  299. else:
  300. self.fortress_exists = False
  301. if self.config['Bonus']['bonus_exists']:
  302. self.bonus = Bonus(self)
  303. self.bonus_exists = True
  304. else:
  305. self.bonus_exists = False
  306. self.destroyedFortresses = 0
  307. self.totalMines = 0
  308. self.destroyedMines = 0
  309. self.totalBonuses = 0
  310. self.capturedBonuses = 0
  311. self.deaths = 0
  312. self.score.pnts = 0
  313. self.score.cntrl = 0
  314. self.score.vlcty = 0
  315. self.score.speed = 0
  316. self.score.flight = 0
  317. self.flight2 = 0
  318. self.mine2 = 0
  319. self.score.fortress = 0
  320. self.score.mines = 0
  321. self.score.bonus = 0
  322. self.score.vlner = 0
  323. self.score.shots = self.config['Missile']['missile_num']
  324. self.flighttimer.reset()
  325. self.mine_list.timer.reset()
  326. if self.config['Graphics']['parallax_mode'] == 'Fortress':
  327. self.starfield_orientation = self.fortress.orientation
  328. else:
  329. self.starfield_orientation = randrange(0, 359)
  330. self.star_velocty_x = math.cos(math.radians(self.starfield_orientation - 180)) * self.config['Graphics']['star_speed']
  331. self.star_velocty_y = math.sin(math.radians(self.starfield_orientation)) * self.config['Graphics']['star_speed']
  332. if self.config['Graphics']['show_starfield']:
  333. self.init_stars()
  334. def draw_pause_overlay(self):
  335. self.pause.draw(self.pause_rect.topleft)
  336. def process_input(self):
  337. """creates game events based on pygame events"""
  338. for event in pygame.event.get():
  339. if self.joystick and self.state == self.STATE_PLAY:
  340. if event.type == pygame.JOYAXISMOTION:
  341. self.gameevents.add("joyaxismotion", event.axis, event.value, type='EVENT_USER')
  342. elif event.type == pygame.JOYBUTTONDOWN:
  343. if event.button == self.fire_button:
  344. self.gameevents.add("press", "fire", type='EVENT_USER')
  345. elif event.button == self.IFF_button:
  346. self.gameevents.add("press", "iff", type='EVENT_USER')
  347. elif event.button == self.shots_button:
  348. self.gameevents.add("press", "shots", type='EVENT_USER')
  349. elif event.button == self.pnts_button:
  350. self.gameevents.add("press", "pnts", type='EVENT_USER')
  351. elif event.type == pygame.JOYBUTTONUP:
  352. if event.button == self.fire_button:
  353. self.gameevents.add("release", "fire", type='EVENT_USER')
  354. elif event.button == self.IFF_button:
  355. self.gameevents.add("release", "iff", type='EVENT_USER')
  356. elif event.button == self.shots_button:
  357. self.gameevents.add("release", "shots", type='EVENT_USER')
  358. elif event.button == self.pnts_button:
  359. self.gameevents.add("release", "pnts", type='EVENT_USER')
  360. else:
  361. if event.type == pygame.KEYDOWN:
  362. if (pygame.key.get_mods() & self.modifier):
  363. if event.key == pygame.K_q:
  364. self.gameevents.add("press", "quit", type='EVENT_USER')
  365. if event.key == pygame.K_RETURN:
  366. if self.state == self.STATE_INTRO:
  367. self.state = self.STATE_SETUP
  368. elif self.state == self.STATE_SETUP:
  369. self.state = self.STATE_GAMENO
  370. elif self.state == self.STATE_GAMENO:
  371. if self.mine_exists:
  372. self.state = self.STATE_SETUP_IFF
  373. else:
  374. self.state = self.STATE_PREPARE
  375. elif self.state == self.STATE_IFF:
  376. self.state = self.STATE_PREPARE
  377. elif self.state == self.STATE_SCORES:
  378. self.state = self.STATE_SETUP
  379. elif self.state == self.STATE_PLAY:
  380. if event.key == self.thrust_key:
  381. self.gameevents.add("press", "thrust", type='EVENT_USER')
  382. elif event.key == self.left_turn_key:
  383. self.gameevents.add("press", "left", type='EVENT_USER')
  384. elif event.key == self.right_turn_key:
  385. self.gameevents.add("press", "right", type='EVENT_USER')
  386. elif event.key == self.fire_key:
  387. self.gameevents.add("press", "fire", type='EVENT_USER')
  388. elif event.key == self.IFF_key:
  389. self.gameevents.add("press", "iff", type='EVENT_USER')
  390. elif event.key == self.shots_key:
  391. self.gameevents.add("press", "shots", type='EVENT_USER')
  392. elif event.key == self.pnts_key:
  393. self.gameevents.add("press", "pnts", type='EVENT_USER')
  394. elif event.key == self.pause_key and self.config['General']['allow_pause']:
  395. self.gameevents.add("press", "pause", type='EVENT_USER')
  396. else:
  397. self.gameevents.add("press", event.key, "user", type='EVENT_SYSTEM')
  398. elif self.state == self.STATE_PAUSED and event.key == self.pause_key:
  399. self.gameevents.add("press", "unpause", type='EVENT_USER')
  400. else:
  401. self.gameevents.add("press", event.key, "user", type='EVENT_SYSTEM')
  402. elif event.type == pygame.KEYUP:
  403. if self.state == self.STATE_PLAY:
  404. if event.key == self.thrust_key:
  405. self.gameevents.add("release", "thrust", type='EVENT_USER')
  406. elif event.key == self.left_turn_key:
  407. self.gameevents.add("release", "left", type='EVENT_USER')
  408. elif event.key == self.right_turn_key:
  409. self.gameevents.add("release", "right", type='EVENT_USER')
  410. elif event.key == self.fire_key:
  411. self.gameevents.add("release", "fire", type='EVENT_USER')
  412. elif event.key == self.IFF_key:
  413. self.gameevents.add("release", "iff", type='EVENT_USER')
  414. elif event.key == self.shots_key:
  415. self.gameevents.add("release", "shots", type='EVENT_USER')
  416. elif event.key == self.pnts_key:
  417. self.gameevents.add("release", "pnts", type='EVENT_USER')
  418. def process_game_logic(self):
  419. """processes game logic to produce game events"""
  420. self.dmod = -1
  421. self.smod = -1
  422. if self.state == self.STATE_SETUP:
  423. if self.current_game < self.config['General']['games_per_session']:
  424. self.current_game += 1
  425. self.state = self.STATE_GAMENO
  426. self.game_title = "Game: %d of %d" % (self.current_game, self.config['General']['games_per_session'])
  427. self.game_title = pygl2d.font.RenderText(self.game_title, (255, 255, 0), self.f36)
  428. self.game_title_rect = self.game_title.get_rect()
  429. self.game_title_rect.center = (self.SCREEN_WIDTH / 2, self.SCREEN_HEIGHT / 16 * 7)
  430. self.gameevents.add("display_game", self.current_game)
  431. else:
  432. self.state = self.STATE_DONE
  433. self.ret = 0
  434. self.lc.stop()
  435. elif self.state == self.STATE_SETUP_IFF:
  436. self.mine_list.generate_foes()
  437. self.gameevents.add("display_foes", " ".join(self.mine_list.foe_letters), "player")
  438. self.foe_top = pygl2d.font.RenderText("The Type-2 mines for this session are:", (255, 255, 0), self.f24)
  439. self.foe_top_rect = self.foe_top.get_rect()
  440. self.foe_top_rect.center = (self.SCREEN_WIDTH / 2, 270 * self.aspect_ratio)
  441. self.foe_middle = pygl2d.font.RenderText(", ".join(self.mine_list.foe_letters), (255, 255, 255), self.f96)
  442. self.foe_middle_rect = self.foe_middle.get_rect()
  443. self.foe_middle_rect.center = (self.SCREEN_WIDTH / 2, self.SCREEN_HEIGHT / 2)
  444. self.foe_midbot = pygl2d.font.RenderText("Try to memorize them before proceeding", (255, 255, 0), self.f24)
  445. self.foe_midbot_rect = self.foe_midbot.get_rect()
  446. self.foe_midbot_rect.center = (self.SCREEN_WIDTH / 2, 500 * self.aspect_ratio)
  447. self.foe_bottom = pygl2d.font.RenderText("Press return to begin", (255, 255, 0), self.f24)
  448. self.foe_bottom_rect = self.foe_bottom.get_rect()
  449. self.foe_bottom_rect.center = (self.SCREEN_WIDTH / 2, 600 * self.aspect_ratio)
  450. self.state = self.STATE_IFF
  451. elif self.state == self.STATE_PREPARE:
  452. self.gameevents.add("game", "ready", type='EVENT_SYSTEM')
  453. self.setup_world()
  454. self.state = self.STATE_PLAY
  455. self.gameevents.add("game", "start", type='EVENT_SYSTEM')
  456. elif self.state == self.STATE_PLAY:
  457. self.ship.compute()
  458. distance = self.ship.get_distance_to_point(self.WORLD_WIDTH / 2, self.WORLD_HEIGHT / 2)
  459. flight_max_inc = self.config['Score']['flight_max_increment']
  460. dmod = 1 - (distance - self.smallhex.radius * 1.125) / (self.WORLD_WIDTH / 2)
  461. if dmod > 1.0: dmod = 1.0
  462. if dmod < 0.0: dmod = 0.0
  463. smod = max([abs(self.ship.velocity.x), abs(self.ship.velocity.y)]) / self.ship.max_vel
  464. self.dmod = dmod
  465. self.smod = smod
  466. for missile in self.missile_list:
  467. missile.compute()
  468. if self.fortress_exists == True:
  469. self.fortress.compute()
  470. for shell in self.shell_list:
  471. shell.compute()
  472. if self.config['Hexagon']['hex_shrink']:
  473. self.bighex.compute()
  474. if self.mine_exists:
  475. if self.mine_list.flag == False and self.mine_list.timer.elapsed() > self.mine_list.spawn_time:
  476. self.gameevents.add("spawn", "mine")
  477. elif self.mine_list.flag and self.mine_list.timer.elapsed() > self.mine_list.timeout:
  478. self.gameevents.add("timeout", "mine")
  479. self.mine_list.compute()
  480. self.check_bounds()
  481. #test collisions to generate game events
  482. self.test_collisions()
  483. if self.flighttimer.elapsed() > self.config['Score']['update_timer']:
  484. self.flighttimer.reset()
  485. def pointspace (a0, a1, a2, b0, b1, b2): return math.exp(a1 ** (a0 * a2)) * math.exp(b1 ** (b0 * b2))
  486. points = flight_max_inc * pointspace(self.dmod, 2, 1, self.smod, 2, 1.75) / pointspace(1, 2, 1, 1, 2, 1.75)
  487. self.gameevents.add("score+", "flight", points)
  488. self.flight2 += flight_max_inc * pointspace(self.dmod, 2, .45, self.smod, 2, 1) / pointspace(1, 2, .45, 1, 2, 1)
  489. if (self.ship.velocity.x ** 2 + self.ship.velocity.y ** 2) ** 0.5 < self.config['Score']['speed_threshold']:
  490. self.gameevents.add("score+", "vlcty", self.config['Score']['VLCTY_increment'])
  491. #self.gameevents.add("score+", "flight", self.config['Score']['VLCTY_increment'])
  492. else:
  493. self.gameevents.add("score-", "vlcty", self.config['Score']['VLCTY_increment'])
  494. #self.gameevents.add("score-", "flight", self.config['Score']['VLCTY_increment'])
  495. if self.bighex.collide(self.ship):
  496. self.gameevents.add("score+", "cntrl", self.config['Score']['CNTRL_increment'])
  497. #self.gameevents.add("score+", "flight", self.config['Score']['CNTRL_increment'])
  498. else:
  499. self.gameevents.add("score+", "cntrl", self.config['Score']['CNTRL_increment'] / 2)
  500. #self.gameevents.add("score+", "flight", self.config['Score']['CNTRL_increment']/2)
  501. if self.bonus_exists:
  502. if self.config['General']['bonus_system'] == "AX-CPT":
  503. self.bonus.axcpt_update()
  504. else:
  505. if self.bonus.visible == False and self.bonus.timer.elapsed() > self.config['Bonus']['symbol_down_time']:
  506. self.gameevents.add("activate", "bonus")
  507. elif self.bonus.visible == True and self.bonus.timer.elapsed() >= self.config['Bonus']['symbol_up_time']:
  508. self.gameevents.add("deactivate", "bonus", self.bonus.current_symbol)
  509. #update scores
  510. self.score.pnts = self.score.__getattribute__("pnts")
  511. self.score.vlcty = self.score.__getattribute__("vlcty")
  512. self.score.cntrl = self.score.__getattribute__("cntrl")
  513. self.score.speed = self.score.__getattribute__("speed")
  514. self.score.flight = self.score.__getattribute__("flight")
  515. self.score.fortress = self.score.__getattribute__("fortress")
  516. self.score.mines = self.score.__getattribute__("mines")
  517. self.score.bonus = self.score.__getattribute__("bonus")
  518. if self.gametimer.elapsed() > self.config['General']['game_time']:
  519. self.gameevents.add("game", "over", type='EVENT_SYSTEM')
  520. self.state = self.STATE_SCORES
  521. def process_events(self):
  522. """processes internal list of game events for this frame"""
  523. gameevents = copy.copy(self.gameevents)
  524. del self.gameevents[:]
  525. while len(gameevents) > 0:
  526. currentevent = gameevents.pop(0)
  527. ticks = currentevent.ticks
  528. time = currentevent.time
  529. eid = currentevent.eid
  530. game = currentevent.game
  531. command = currentevent.command
  532. obj = currentevent.obj
  533. target = currentevent.target
  534. type = currentevent.type
  535. if self.config['Logging']['logging'] and currentevent.log:
  536. self.log.write("%s\t%f\t%d\t%d\t%d\t%s\t%s\t%s\n" % (type, time, ticks, game, eid, command, obj, target))
  537. if command == "press":
  538. if obj == "pause":
  539. self.gametimer.pause()
  540. self.state = self.STATE_PAUSED
  541. elif obj == "unpause":
  542. self.state = self.STATE_PLAY
  543. self.gametimer.unpause()
  544. elif obj == "quit":
  545. self.lc.stop()
  546. elif obj == "left":
  547. self.ship.turn_left_flag = True
  548. elif obj == "right":
  549. self.ship.turn_right_flag = True
  550. elif obj == "thrust":
  551. self.ship.thrust_flag = True
  552. elif obj == "fire":
  553. self.ship.fire()
  554. elif obj == "iff":
  555. #print len(self.mine_list)
  556. #don't do anything if there's no mine on the screen
  557. if len(self.mine_list) == 0:
  558. pass
  559. elif self.mine_list[0].tagged == "fail":
  560. self.gameevents.add("tag", "already_failed")
  561. elif self.mine_list[0].tagged == "disable":
  562. self.gameevents.add("tag", "already_disabled")
  563. elif self.mine_list[0].tagged == "tagged":
  564. self.gameevents.add("tag", "already_tagged")
  565. #if the mine is untagged and this is the first tap
  566. elif self.mine_list[0].tagged == "untagged" and self.mine_list.iff_flag == False:
  567. if self.score.iff in self.mine_list.foe_letters:
  568. self.gameevents.add("first_tag", "foe")
  569. else:
  570. self.gameevents.add("first_tag", "friend_fail")
  571. #if the mine is a foe, untagged, and this is the second tap, check timer, set intrvl
  572. elif self.mine_list[0].tagged == "untagged" and self.mine_list.iff_flag:
  573. self.score.intrvl = self.mine_list.iff_timer.elapsed()
  574. if (self.mine_list.iff_timer.elapsed() > self.config['Mine']['intrvl_min']) and (self.mine_list.iff_timer.elapsed() < self.config['Mine']['intrvl_max']):
  575. self.gameevents.add("second_tag", "foe")
  576. else:
  577. self.gameevents.add("second_tag", "out_of_bounds")
  578. elif obj == "shots":
  579. if not self.bonus_captured:
  580. self.bonus_captured = True
  581. if self.config['General']['bonus_system'] == "standard":
  582. #if current symbol is bonus but previous wasn't, set flag to deny bonus if next symbol happens to be the bonus symbol
  583. if (self.bonus.current_symbol == self.bonus.bonus_symbol) and (self.bonus.prior_symbol != self.bonus.bonus_symbol):
  584. self.bonus.flag = True
  585. self.gameevents.add("flagged_for_first_bonus")
  586. if (self.bonus.current_symbol == self.bonus.bonus_symbol) and (self.bonus.prior_symbol == self.bonus.bonus_symbol):
  587. #bonus available, check flag to award or deny bonus
  588. if self.bonus.flag:
  589. self.gameevents.add("attempt_to_capture_flagged_bonus")
  590. else:
  591. self.capturedBonuses += 1
  592. self.gameevents.add("shots_bonus_capture")
  593. self.gameevents.add("score+", "shots", self.config['Score']['bonus_missiles'])
  594. self.gameevents.add("score+", "bonus", self.config['Score']['bonus_points'] / 2)
  595. self.bonus.flag = True
  596. else: #AX-CPT
  597. if self.bonus.axcpt_flag == True and (self.bonus.state == "iti" or self.bonus.state == "target") and self.bonus.current_pair == "ax":
  598. self.snd_bonus_success.play()
  599. self.capturedBonuses += 1
  600. self.gameevents.add("shots_bonus_capture")
  601. self.gameevents.add("score+", "shots", self.config['Score']['bonus_missiles'])
  602. if self.config['General']['next_gen']:
  603. self.gameevents.add("score+", "pnts", self.config['Score']['bonus_points'] / 2)
  604. else:
  605. self.gameevents.add("score+", "bonus", self.config['Score']['bonus_points'] / 2)
  606. elif self.bonus.axcpt_flag:
  607. self.bonus.axcpt_flag = False
  608. self.snd_bonus_fail.play()
  609. self.gameevents.add("shots_bonus_failure")
  610. if self.config['General']['next_gen']:
  611. self.gameevents.add("score-", "pnts", self.config['Score']['bonus_points'] / 2)
  612. else:
  613. self.gameevents.add("score-", "bonus", self.config['Score']['bonus_points'] / 2)
  614. elif obj == "pnts":
  615. if not self.bonus_captured:
  616. self.bonus_captured = True
  617. if self.config['General']['bonus_system'] == "standard":
  618. #if current symbol is bonus but previous wasn't, set flag to deny bonus if next symbol happens to be the bonus symbol
  619. if (self.bonus.current_symbol == self.bonus.bonus_symbol) and (self.bonus.prior_symbol != self.bonus.bonus_symbol):
  620. self.bonus.flag = True
  621. self.gameevents.add("flagged_for_first_bonus")
  622. if (self.bonus.current_symbol == self.bonus.bonus_symbol) and (self.bonus.prior_symbol == self.bonus.bonus_symbol):
  623. #bonus available, check flag to award or deny bonus
  624. if self.bonus.flag:
  625. self.gameevents.add("attempt_to_capture_flagged_bonus")
  626. else:
  627. self.capturedBonuses += 1
  628. self.gameevents.add("pnts_pnts_capture")
  629. self.gameevents.add("score+", "bonus", self.config['Score']['bonus_points'])
  630. self.gameevents.add("score+", "pnts", self.config['Score']['bonus_points'])
  631. self.bonus.flag = True
  632. else: #AX-CPT
  633. if self.bonus.axcpt_flag == True and (self.bonus.state == "iti" or self.bonus.state == "target") and self.bonus.current_pair == "ax":
  634. self.snd_bonus_success.play()
  635. self.capturedBonuses += 1
  636. self.gameevents.add("pnts_bonus_capture")
  637. if self.config['General']['next_gen']:
  638. self.gameevents.add("score+", "pnts", self.config['Score']['bonus_points'])
  639. else:
  640. self.gameevents.add("score+", "pnts", self.config['Score']['bonus_points'])
  641. self.gameevents.add("score+", "bonus", self.config['Score']['bonus_points'])
  642. elif self.bonus.axcpt_flag:
  643. self.bonus.axcpt_flag = False
  644. self.snd_bonus_fail.play()
  645. self.gameevents.add("pnts_bonus_failure")
  646. if self.config['General']['next_gen']:
  647. self.gameevents.add("score-", "pnts", self.config['Score']['bonus_points'] / 2)
  648. else:
  649. self.gameevents.add("score-", "bonus", self.config['Score']['bonus_points'] / 2)
  650. elif command == "destroyed":
  651. if obj == "ship":
  652. self.deaths += 1
  653. self.reset_position()
  654. self.reset_mines()
  655. elif command == "bonus_available":
  656. self.totalBonuses += 1
  657. elif command == "first_tag":
  658. if obj == "foe":
  659. self.mine_list.iff_flag = True
  660. self.mine_list.iff_timer.reset()
  661. elif len(self.mine_list) > 0:
  662. self.mine_list[0].tagged = "fail"
  663. elif command == "second_tag":
  664. self.mine_list.iff_flag = False
  665. if obj == "foe" and len(self.mine_list) > 0:
  666. self.mine_list[0].tagged = "tagged"
  667. elif command == "release":
  668. if obj == "left":
  669. self.ship.turn_left_flag = False
  670. elif obj == "right":
  671. self.ship.turn_right_flag = False
  672. elif obj == "thrust":
  673. self.ship.thrust_flag = False
  674. elif command == "warp":
  675. self.gameevents.add("score-", "pnts", self.config['Score']['warp_penalty'])
  676. self.gameevents.add("score-", "flight", self.config['Score']['warp_penalty'])
  677. elif command == "activate":
  678. if obj == "bonus":
  679. self.bonus.visible = True
  680. self.bonus.timer.reset()
  681. self.bonus.get_new_symbol()
  682. self.gameevents.add("new_bonus", self.bonus.current_symbol, self.bonus.prior_symbol)
  683. if self.bonus.current_symbol == self.bonus.prior_symbol == self.bonus.bonus_symbol:
  684. self.gameevents.add("bonus_available")
  685. #"reset" the bonus flag (which prevents premature capture) if symbol is not bonus
  686. if self.bonus.current_symbol != self.bonus.bonus_symbol:
  687. self.bonus.flag = False
  688. elif command == "deactivate":
  689. if obj == "bonus":
  690. self.bonus.visible = False
  691. self.bonus.timer.reset()
  692. elif command == "spawn":
  693. self.totalMines += 1
  694. self.mine_list.flag = True
  695. self.mine_list.timer.reset()
  696. self.mine_list.add()
  697. if self.mine_list[0].iff in self.mine_list.foe_letters:
  698. self.gameevents.add("new_mine", "foe")
  699. else:
  700. self.gameevents.add("new_mine", "friend")
  701. elif command == "timeout":
  702. self.mine_list.flag = False
  703. self.mine_list.iff_flag = False
  704. self.mine_list.timer.reset()
  705. if len(self.mine_list) > 0:
  706. del self.mine_list[0]
  707. self.score.iff = ''
  708. self.score.intrvl = 0
  709. self.gameevents.add("score-", "mines", self.config['Score']['mine_timeout_penalty'])
  710. elif command == "score++":
  711. if obj == "bonus_points":
  712. self.gameevents.add("score+", "pnts", int(target))
  713. elif command == "score+":
  714. self.score.__setattr__(obj, self.score.__getattribute__(obj) + float(target))
  715. if self.score.shots > self.config['Missile']['missile_max']:
  716. self.score.shots = self.config['Missile']['missile_max']
  717. elif command == "score-":
  718. self.score.__setattr__(obj, self.score.__getattribute__(obj) - float(target))
  719. elif command == "collide":
  720. self.process_collision(obj, target)
  721. elif command == "joyaxismotion":
  722. if obj == 0:
  723. self.ship.joy_turn = target
  724. elif obj == 1:
  725. self.ship.joy_thrust = target
  726. def process_collision(self, obj, target):
  727. """process single collision event"""
  728. if obj == "small_hex" and not self.smallhex.small_hex_flag:
  729. self.ship.velocity.x = -self.ship.velocity.x
  730. self.ship.velocity.y = -self.ship.velocity.y
  731. self.gameevents.add("score-", "pnts", self.config['Score']['small_hex_penalty'])
  732. self.gameevents.add("score-", "flight", self.config['Score']['small_hex_penalty'])
  733. self.smallhex.small_hex_flag = True
  734. elif obj == "shell":
  735. #remove shell, target is index of shell in shell_list
  736. del self.shell_list[target]
  737. self.gameevents.add("score-", "pnts", self.config['Score']['shell_hit_penalty'])
  738. self.gameevents.add("score-", "fortress", self.config['Score']['shell_hit_penalty'])
  739. self.ship.take_damage()
  740. if not self.ship.alive:
  741. self.gameevents.add("destroyed", "ship", "shell")
  742. self.gameevents.add("score-", "pnts", self.config['Score']['ship_death_penalty'])
  743. self.gameevents.add("score-", "fortress", self.config['Score']['ship_death_penalty'])
  744. self.ship.color = (255, 255, 0)
  745. elif self.config['Ship']['colored_damage']:
  746. g = 255 / self.ship.start_health * (self.ship.health - 1)
  747. self.ship.color = (255, g, 0)
  748. elif obj.startswith("missile_"):
  749. #if missile hits fortress, need to check if it takes damage when mine is onscreen
  750. if target == "fortress" and (len(self.mine_list) == 0 or self.config['Fortress']['hit_fortress_while_mine']):
  751. if self.ship.shot_timer.elapsed() >= self.config['Fortress']['vlner_time']:
  752. self.gameevents.add("score+", "vlner", 1)
  753. if self.ship.shot_timer.elapsed() < self.config['Fortress']['vlner_time'] and self.score.vlner >= self.config['Fortress']['vlner_threshold']:
  754. self.gameevents.add("destroyed", "fortress")
  755. self.fortress.alive = False
  756. #r = choice([0,45,90,135,180,225,270,315])
  757. #if r:
  758. # self.explosion.rotate(r)
  759. self.fortress.reset_timer.reset()
  760. self.snd_explosion.play()
  761. self.gameevents.add("score+", "pnts", self.config['Score']['destroy_fortress'])
  762. self.gameevents.add("score+", "fortress", self.config['Score']['destroy_fortress'])
  763. self.score.vlner = 0
  764. self.destroyedFortresses += 1
  765. self.gameevents.add("reset", "VLNER")
  766. #do we reset the mine timer?
  767. if self.config['Mine']['fortress_resets_mine']:
  768. self.mine_list.timer.reset()
  769. self.mine_list.flag = False
  770. elif self.ship.shot_timer.elapsed() < self.config['Fortress']['vlner_time'] and self.score.vlner < self.config['Fortress']['vlner_threshold']:
  771. self.gameevents.add("reset", "VLNER")
  772. self.score.vlner = 0
  773. self.snd_vlner_reset.play()
  774. self.ship.shot_timer.reset()
  775. elif target.startswith("mine_"):
  776. #deal with missile hitting mine
  777. #can the mine be hit?
  778. if len(self.mine_list) > 0:
  779. if self.mine_list[0].tagged == "fail":
  780. self.gameevents.add("collide", "fail_tagged_mine")
  781. elif self.mine_list[0].tagged == "disabled":
  782. self.gameevents.add("collide", "disable_tagged_mine")
  783. elif self.mine_list[0].tagged == "untagged":
  784. if self.score.iff in self.mine_list.foe_letters:
  785. self.mine_list[0].tagged = "disable"
  786. self.gameevents.add("collide", "untagged_foe_mine")
  787. else:
  788. self.gameevents.add("collide", "friend_mine")
  789. elif self.mine_list[0].tagged == "tagged" and self.score.iff in self.mine_list.foe_letters:
  790. self.gameevents.add("collide", "tagged_foe_mine")
  791. elif obj.startswith("mine_"):
  792. #mine hit the ship
  793. index = int(obj[-1])
  794. #check to see if mine is still alive, it is possible to shot and
  795. #collide with a mine at the same time, ties go to ship
  796. if index < len(self.mine_list):
  797. del self.mine_list[index]
  798. self.score.iff = ''
  799. self.score.intrvl = 0
  800. self.mine_list.flag = False
  801. self.mine_list.iff_flag = False
  802. self.mine_list.timer.reset()
  803. self.gameevents.add("score-", "pnts", self.config['Score']['mine_hit_penalty'])
  804. self.gameevents.add("score-", "mines", self.config['Score']['mine_hit_penalty'])
  805. self.mine2 -= self.config['Score']['mine_hit_penalty']
  806. self.ship.take_damage()
  807. if not self.ship.alive:
  808. self.gameevents.add("destroyed", "ship", "mine")
  809. self.gameevents.add("score-", "pnts", self.config['Score']['ship_death_penalty'])
  810. self.gameevents.add("score-", "mines", self.config['Score']['ship_death_penalty'])
  811. self.mine2 -= self.config['Score']['ship_death_penalty']
  812. self.ship.color = (255, 255, 0)
  813. elif self.config['Ship']['colored_damage']:
  814. g = 255 / self.ship.start_health * (self.ship.health - 1)
  815. self.ship.color = (255, g, 0)
  816. elif obj == "friend_mine":
  817. #get rid of mine
  818. self.destroyedMines += 1
  819. self.mine_list.flag = False
  820. self.mine_list.iff_flag = False
  821. self.gameevents.add("score+", "mines", self.config['Score']['energize_friend'])
  822. self.gameevents.add("score+", "pnts", self.config['Score']['energize_friend'])
  823. #see how long mine has been alive. 0-100 points if destroyed within 10 seconds
  824. self.gameevents.add("score+", "mines", 100 - 10 * math.floor(self.mine_list.timer.elapsed() / 1000))
  825. self.gameevents.add("score+", "speed", 100 - 10 * math.floor(self.mine_list.timer.elapsed() / 1000))
  826. #print self.mine_list.timer.elapsed()
  827. #print 100 - 10 * math.floor(self.mine_list.timer.elapsed()/1000)
  828. self.mine_list.timer.reset()
  829. self.mine2 += 50
  830. #amazingly, missile can hit the mine in the same frame as the mine hits the ship
  831. if len(self.mine_list) > 0:
  832. del self.mine_list[0]
  833. self.score.iff = ''
  834. self.score.intrvl = 0
  835. elif obj == "tagged_foe_mine":
  836. #get rid of mine
  837. self.destroyedMines += 1
  838. self.mine_list.flag = False
  839. self.mine_list.iff_flag = False
  840. self.gameevents.add("score+", "mines", self.config['Score']['destroy_foe'])
  841. self.gameevents.add("score+", "pnts", self.config['Score']['destroy_foe'])
  842. #see how long mine has been alive. 0-100 points if destroyed within 10 seconds
  843. self.gameevents.add("score+", "mines", 100 - 10 * math.floor(self.mine_list.timer.elapsed() / 1000))
  844. self.gameevents.add("score+", "speed", 100 - 10 * math.floor(self.mine_list.timer.elapsed() / 1000))
  845. self.mine_list.timer.reset()
  846. self.mine2 += 75
  847. if len(self.mine_list) > 0:
  848. del self.mine_list[0]
  849. self.score.iff = ''
  850. self.score.intrvl = 0
  851. def reset_mines(self):
  852. del self.mine_list[:]
  853. self.mine_list.flag = False
  854. self.mine_list.iff_flag = False
  855. self.mine_list.timer.reset()
  856. def test_collisions(self):
  857. """test collisions between relevant game entities"""
  858. if self.fortress_exists:
  859. if self.smallhex.collide(self.ship):
  860. self.gameevents.add("collide", "small_hex", "ship")
  861. else:
  862. self.smallhex.small_hex_flag = False
  863. for i, shell in enumerate(self.shell_list):
  864. if shell.collide(self.ship):
  865. self.gameevents.add("collide", "shell", i)
  866. #need to treat this carefully - the mine can overlap the fortress, so we don't want to remove the same missile twice
  867. for i, missile in enumerate(self.missile_list):
  868. del_missile = False
  869. if self.fortress_exists and missile.collide(self.fortress):
  870. self.gameevents.add("collide", "missile_" + str(i), "fortress")
  871. del_missile = True
  872. for j, mine in enumerate(self.mine_list):
  873. if missile.collide(mine) and not missile.collide(self.fortress):
  874. self.gameevents.add("collide", "missile_" + str(i), "mine_" + str(j))
  875. del_missile = True
  876. if del_missile:
  877. del self.missile_list[i]
  878. for i, mine in enumerate(self.mine_list):
  879. if mine.collide(self.ship):
  880. self.gameevents.add("collide", "mine_" + str(i), "ship")
  881. def check_bounds(self):
  882. """determine whether any shells or missiles have left the world"""
  883. for i, missile in enumerate(self.missile_list):
  884. if missile.out_of_bounds(self.world):
  885. del self.missile_list[i]
  886. self.gameevents.add("bounds_remove", "missile")
  887. for i, shell in enumerate(self.shell_list):
  888. if shell.out_of_bounds(self.world):
  889. del self.shell_list[i]
  890. self.gameevents.add("bounds_remove", "shell")
  891. def reset_position(self):
  892. """pauses the game and resets"""
  893. self.snd_explosion.play()
  894. pygame.time.delay(1000)
  895. self.score.iff = ""
  896. self.ship.alive = True
  897. self.ship.position.x = self.world.left + self.config['Ship']['ship_pos_x'] * self.aspect_ratio
  898. self.ship.position.y = self.world.top + self.config['Ship']['ship_pos_y'] * self.aspect_ratio
  899. self.ship.velocity.x = self.config['Ship']['ship_vel_x']
  900. self.ship.velocity.y = self.config['Ship']['ship_vel_y']
  901. self.ship.orientation = self.config['Ship']['ship_orientation']
  902. def draw_stars(self):
  903. stars = [[], [], []]
  904. for star in self.stars:
  905. if self.state == self.STATE_PLAY:
  906. star[0] += star[2] * self.star_velocty_x
  907. star[1] += star[2] * self.star_velocty_y
  908. if star[0] >= self.world.right - self.linewidth:
  909. star[0] = self.world.left + self.linewidth
  910. star[1] = randrange(self.world.top + self.linewidth, self.world.bottom - self.linewidth)
  911. star[2] = choice([1, 2, 3])
  912. elif star[0] <= self.world.left + self.linewidth:
  913. star[0] = self.world.right - self.linewidth
  914. star[1] = randrange(self.world.top + self.linewidth, self.world.bottom - self.linewidth)
  915. star[2] = choice([1, 2, 3])
  916. elif star[1] >= self.world.bottom - self.linewidth:
  917. star[1] = self.world.top + self.linewidth
  918. star[0] = randrange(self.world.left + self.linewidth, self.world.right - self.linewidth)
  919. star[2] = choice([1, 2, 3])
  920. elif star[1] <= self.world.top + self.linewidth:
  921. star[1] = self.world.bottom - self.linewidth
  922. star[0] = randrange(self.world.left + self.linewidth, self.world.right - self.linewidth)
  923. star[2] = choice([1, 2, 3])
  924. stars[star[2] - 1].append((star[0], star[1]))
  925. pygl2d.draw.points2(stars[0], (100, 100, 100), 1)
  926. pygl2d.draw.points2(stars[1], (190, 190, 190), 2)
  927. pygl2d.draw.points2(stars[2], (255, 255, 255), 3)
  928. def draw_world(self):
  929. if self.config['Graphics']['max_stars']:
  930. self.draw_stars()
  931. if not self.config['Hexagon']['hide_big_hex']:
  932. self.bighex.draw()
  933. if self.fortress_exists and not self.fortress.alive:
  934. pass
  935. else:
  936. if not self.config['Hexagon']['hide_small_hex']:
  937. self.smallhex.draw()
  938. for shell in self.shell_list:
  939. shell.draw()
  940. if self.fortress_exists:
  941. if self.fortress.alive:
  942. self.fortress.draw()
  943. else:
  944. self.explosion_rect.center = (self.fortress.position.x, self.fortress.position.y)
  945. self.explosion.draw(self.explosion_rect.topleft)
  946. for missile in self.missile_list:
  947. missile.draw()
  948. if self.ship.alive:
  949. self.ship.draw()
  950. else:
  951. self.explosion_small_rect.center = (self.ship.position.x, self.ship.position.y)
  952. self.explosion_small.draw(self.explosion_small_rect.topleft)
  953. self.mine_list.draw()
  954. if self.bonus_exists and self.bonus.visible:
  955. self.bonus.draw()
  956. def draw(self):
  957. """draws the world"""
  958. pygl2d.display.begin_draw(self.screen_size)
  959. if self.state == self.STATE_INTRO:
  960. self.draw_intro()
  961. elif self.state == self.STATE_GAMENO:
  962. self.draw_game_number()
  963. elif self.state == self.STATE_IFF:
  964. self.draw_foe_mines()
  965. elif self.state == self.STATE_PLAY or self.state == self.STATE_PAUSED:
  966. if self.state == self.STATE_PAUSED and self.config['Display']['pause_overlay']:
  967. self.draw_pause_overlay()
  968. else:
  969. pygl2d.draw.polygon([self.screen_rect.topleft, self.screen_rect.topright, self.screen_rect.bottomright, self.screen_rect.bottomleft], (64, 64, 64), stipple_pattern=self.happy[::-1])
  970. self.frame.draw()
  971. self.score.draw()
  972. with scissor_box(self.world):
  973. self.draw_world()
  974. elif self.state == self.STATE_SCORES:
  975. self.draw_scores()
  976. self.gameevents.add("display", 'preflip', 'main', False, type='EVENT_SYSTEM')
  977. pygl2d.display.end_draw()
  978. def log_world(self):
  979. """logs current state of world to logfile"""
  980. system_time = get_time()
  981. game_time = pygame.time.get_ticks()
  982. if self.state == 2:
  983. smod = self.smod
  984. dmod = self.dmod
  985. else:
  986. smod = "NA"
  987. dmod = "NA"
  988. if self.ship and self.ship.alive:
  989. ship_alive = "y"
  990. ship_x = "%.3f" % (self.ship.position.x)
  991. ship_y = "%.3f" % (self.ship.position.y)
  992. ship_vel_x = "%.3f" % (self.ship.velocity.x)
  993. ship_vel_y = "%.3f" % (self.ship.velocity.y)
  994. ship_orientation = "%.3f" % (self.ship.orientation)
  995. ship_health = str(self.ship.health)
  996. distance = str(self.ship.get_distance_to_point(self.WORLD_WIDTH / 2, self.WORLD_HEIGHT / 2))
  997. else:
  998. ship_alive = "n"
  999. ship_x = "NA"
  1000. ship_y = "NA"
  1001. ship_vel_x = "NA"
  1002. ship_vel_y = "NA"
  1003. ship_orientation = "NA"
  1004. ship_health = "NA"
  1005. distance = "NA"
  1006. if len(self.mine_list) > 0:
  1007. mine_no = self.mine_list.mine_count
  1008. mine_id = self.mine_list[0].iff
  1009. else:
  1010. mine_no = "NA"
  1011. mine_id = "NA"
  1012. if self.fortress and self.fortress_exists and self.fortress.alive:
  1013. fortress_alive = "y"
  1014. fortress_orientation = str(self.fortress.orientation)
  1015. fortress_x = str(self.fortress.position.x)
  1016. fortress_y = str(self.fortress.position.y)
  1017. else:
  1018. fortress_alive = "n"
  1019. fortress_orientation = "NA"
  1020. fortress_x = "NA"
  1021. fortress_y = "NA"
  1022. if self.bonus and self.config['General']['bonus_system'] == "AX-CPT":
  1023. bonus_isi = str(self.bonus.isi_time)
  1024. else:
  1025. bonus_isi = 'NA'
  1026. if self.bonus and self.bonus.visible:
  1027. bonus_no = self.bonus.bonus_count
  1028. bonus_cur_x = self.bonus.position.x
  1029. bonus_cur_y = self.bonus.position.y
  1030. else:
  1031. bonus_no = "NA"
  1032. bonus_cur_x = "NA"
  1033. bonus_cur_y = "NA"
  1034. if not self.bonus or self.bonus.current_symbol == '':
  1035. bonus_cur = "NA"
  1036. else:
  1037. bonus_cur = self.bonus.current_symbol
  1038. if not self.bonus or self.bonus.prior_symbol == '':
  1039. bonus_prev = "NA"
  1040. else:
  1041. bonus_prev = self.bonus.prior_symbol
  1042. if not self.score and self.score.iff == '':
  1043. iff_score = 'NA'
  1044. else:
  1045. iff_score = self.score.iff
  1046. keys = pygame.key.get_pressed()
  1047. if keys[self.thrust_key]:
  1048. thrust_key = "y"
  1049. else:
  1050. thrust_key = "n"
  1051. if keys[self.left_turn_key]:
  1052. left_key = "y"
  1053. else:
  1054. left_key = "n"
  1055. if keys[self.right_turn_key]:
  1056. right_key = "y"
  1057. else:
  1058. right_key = "n"
  1059. if keys[self.fire_key]:
  1060. fire_key = "y"
  1061. else:
  1062. fire_key = "n"
  1063. if keys[self.IFF_key]:
  1064. iff_key = "y"
  1065. else:
  1066. iff_key = "n"
  1067. if keys[self.shots_key]:
  1068. shots_key = "y"
  1069. else:
  1070. shots_key = "n"
  1071. if keys[self.pnts_key]:
  1072. pnts_key = "y"
  1073. else:
  1074. pnts_key = "n"
  1075. data = ["STATE", system_time, game_time, self.current_game, "NA", "NA", "NA", "NA",
  1076. " ".join(self.mine_list.foe_letters), ship_alive, ship_health, ship_x, ship_y,
  1077. smod, dmod, ship_vel_x, ship_vel_y, ship_orientation, distance, mine_no, mine_id,
  1078. self.mine_list, fortress_alive, fortress_x, fortress_y, fortress_orientation,
  1079. self.missile_list, self.shell_list]
  1080. if self.config['General']['bonus_system'] == "AX-CPT":
  1081. data = data + [ bonus_no, bonus_prev, bonus_cur, bonus_cur_x, bonus_cur_y, bonus_isi ]
  1082. else:
  1083. data = data + [ bonus_no, bonus_prev, bonus_cur, bonus_cur_x, bonus_cur_y ]
  1084. data = data + [self.score.pnts, self.score.cntrl, self.score.vlcty,
  1085. self.score.vlner, iff_score, self.score.intrvl, self.score.speed,
  1086. self.score.shots, self.score.flight, self.flight2, self.score.fortress,
  1087. self.score.mines, self.mine2, self.score.bonus, thrust_key, left_key,
  1088. right_key, fire_key, iff_key, shots_key, pnts_key]
  1089. for name in self.plugins:
  1090. if hasattr(self.plugins[name], "logCallback"):
  1091. data = data + self.plugins[name].logCallback()
  1092. self.log.write("\t".join(map(str, data)) + "\n")
  1093. def draw_intro(self):
  1094. """display intro scene"""
  1095. self.intro_title.draw(self.intro_title_rect.topleft)
  1096. self.intro_vers.draw(self.intro_vers_rect.topleft)
  1097. self.intro_copy.draw(self.intro_copy_rect.topleft)
  1098. self.intro_logo.draw(self.intro_logo_rect.topleft)
  1099. def draw_game_number(self):
  1100. """before game begins, present the game number"""
  1101. self.game_title.draw(self.game_title_rect.topleft)
  1102. pygl2d.draw.line((self.SCREEN_WIDTH / 4 , self.SCREEN_HEIGHT / 16 * 8.5), (self.SCREEN_WIDTH / 4 * 3, self.SCREEN_HEIGHT / 16 * 8.5), (255, 255, 255))
  1103. pygl2d.draw.line((self.SCREEN_WIDTH / 4 , self.SCREEN_HEIGHT / 16 * 5.5), (self.SCREEN_WIDTH / 4 * 3, self.SCREEN_HEIGHT / 16 * 5.5), (255, 255, 255))
  1104. def draw_foe_mines(self):
  1105. """before game begins, present the list of IFF letters to target"""
  1106. self.foe_top.draw(self.foe_top_rect.topleft)
  1107. self.foe_middle.draw(self.foe_middle_rect.topleft)
  1108. self.foe_midbot.draw(self.foe_midbot_rect.topleft)
  1109. self.foe_bottom.draw(self.foe_bottom_rect.topleft)
  1110. def draw_old_score(self):
  1111. """shows score for last game and waits to continue"""
  1112. pygame.event.get() #clear event list? Otherwise it skips
  1113. self.screen.fill((0, 0, 0))
  1114. gamesurf = self.f36.render("Game %d" % (self.current_game), True, (255, 255, 0))
  1115. gamerect = gamesurf.get_rect()
  1116. gamerect.centery = self.SCREEN_HEIGHT / 16 * 2
  1117. gamerect.centerx = self.SCREEN_WIDTH / 2
  1118. self.screen.blit(gamesurf, gamerect)
  1119. pygame.draw.line(self.screen, (255, 255, 255), (self.SCREEN_WIDTH / 4 , self.SCREEN_HEIGHT / 16 * 3), (self.SCREEN_WIDTH / 4 * 3, self.SCREEN_HEIGHT / 16 * 3))
  1120. pntssurf = self.f24.render("PNTS score:", True, (255, 255, 0))
  1121. pntsrect = pntssurf.get_rect()
  1122. pntsrect.left = self.SCREEN_WIDTH / 3
  1123. pntsrect.centery = self.SCREEN_HEIGHT / 16 * 4
  1124. self.screen.blit(pntssurf, pntsrect)
  1125. cntrlsurf = self.f24.render("CNTRL score:", True, (255, 255, 0))
  1126. cntrlrect = cntrlsurf.get_rect()
  1127. cntrlrect.left = self.SCREEN_WIDTH / 3
  1128. cntrlrect.centery = self.SCREEN_HEIGHT / 16 * 6
  1129. self.screen.blit(cntrlsurf, cntrlrect)
  1130. vlctysurf = self.f24.render("VLCTY score:", True, (255, 255, 0))
  1131. vlctyrect = vlctysurf.get_rect()
  1132. vlctyrect.left = self.SCREEN_WIDTH / 3
  1133. vlctyrect.centery = self.SCREEN_HEIGHT / 16 * 8
  1134. self.screen.blit(vlctysurf, vlctyrect)
  1135. speedsurf = self.f24.render("SPEED score:", True, (255, 255, 0))
  1136. speedrect = speedsurf.get_rect()
  1137. speedrect.left = self.SCREEN_WIDTH / 3
  1138. speedrect.centery = self.SCREEN_HEIGHT / 16 * 10
  1139. self.screen.blit(speedsurf, speedrect)
  1140. pntsnsurf = self.f24.render("%d" % self.score.pnts, True, (255, 255, 255))
  1141. pntsnrect = pntsnsurf.get_rect()
  1142. pntsnrect.right = self.SCREEN_WIDTH / 3 * 2
  1143. pntsnrect.centery = self.SCREEN_HEIGHT / 16 * 4
  1144. self.screen.blit(pntsnsurf, pntsnrect)
  1145. cntrlnsurf = self.f24.render("%d" % self.score.cntrl, True, (255, 255, 255))
  1146. cntrlnrect = cntrlnsurf.get_rect()
  1147. cntrlnrect.right = self.SCREEN_WIDTH / 3 * 2
  1148. cntrlnrect.centery = self.SCREEN_HEIGHT / 16 * 6
  1149. self.screen.blit(cntrlnsurf, cntrlnrect)
  1150. vlctynsurf = self.f24.render("%d" % self.score.vlcty, True, (255, 255, 255))
  1151. vlctynrect = vlctynsurf.get_rect()
  1152. vlctynrect.right = self.SCREEN_WIDTH / 3 * 2
  1153. vlctynrect.centery = self.SCREEN_HEIGHT / 16 * 8
  1154. self.screen.blit(vlctynsurf, vlctynrect)
  1155. speednsurf = self.f24.render("%d" % self.score.speed, True, (255, 255, 255))
  1156. speednrect = speednsurf.get_rect()
  1157. speednrect.right = self.SCREEN_WIDTH / 3 * 2
  1158. speednrect.centery = self.SCREEN_HEIGHT / 16 * 10
  1159. self.screen.blit(speednsurf, speednrect)
  1160. #draw line
  1161. pygame.draw.line(self.screen, (255, 255, 255), (self.SCREEN_WIDTH / 4 , self.SCREEN_HEIGHT / 16 * 11), (self.SCREEN_WIDTH / 4 * 3, self.SCREEN_HEIGHT / 16 * 11))
  1162. totalsurf = self.f24.render("Total game score:", True, (255, 255, 0))
  1163. totalrect = totalsurf.get_rect()
  1164. totalrect.left = self.SCREEN_WIDTH / 3
  1165. totalrect.centery = self.SCREEN_HEIGHT / 16 * 12
  1166. self.screen.blit(totalsurf, totalrect)
  1167. totalnsurf = self.f24.render("%d" % (self.score.pnts + self.score.cntrl + self.score.vlcty + self.score.speed), True, (255, 255, 255))
  1168. totalnrect = totalnsurf.get_rect()
  1169. totalnrect.right = self.SCREEN_WIDTH / 3 * 2
  1170. totalnrect.centery = self.SCREEN_HEIGHT / 16 * 12
  1171. self.screen.blit(totalnsurf, totalnrect)
  1172. if self.current_game == self.config['General']['games_per_session']:
  1173. finalsurf = self.f24.render("You're done! Press return to exit", True, (0, 255, 0))
  1174. else:
  1175. finalsurf = self.f24.render("Press return for next game", True, (0, 255, 0))
  1176. finalrect = finalsurf.get_rect()
  1177. finalrect.centerx = self.SCREEN_WIDTH / 2
  1178. finalrect.centery = self.SCREEN_HEIGHT / 16 * 14
  1179. self.screen.blit(finalsurf, finalrect)
  1180. def draw_ng_score(self, time):
  1181. pygame.event.get() #clear event list? Otherwise it skips
  1182. #self.screen.fill((0, 0, 0))
  1183. gamesurf = pygl2d.font.RenderText("Game %d Stats" % (self.current_game), (255, 255, 0), self.f36)
  1184. gamerect = gamesurf.get_rect()
  1185. gamerect.centery = self.SCREEN_HEIGHT / 16 * 2
  1186. gamerect.centerx = self.SCREEN_WIDTH / 2
  1187. gamesurf.draw(gamerect.topleft)
  1188. pygl2d.draw.line((self.SCREEN_WIDTH / 4 , self.SCREEN_HEIGHT / 16 * 3), (self.SCREEN_WIDTH / 4 * 3, self.SCREEN_HEIGHT / 16 * 3), (255, 255, 255))
  1189. pntssurf = pygl2d.font.RenderText("Points:", (255, 255, 0), self.f24)
  1190. pntsrect = pntssurf.get_rect()
  1191. pntsrect.left = self.SCREEN_WIDTH / 3
  1192. pntsrect.centery = self.SCREEN_HEIGHT / 16 * 4
  1193. pntssurf.draw(pntsrect.topleft)
  1194. pntsnsurf = pygl2d.font.RenderText("%d" % self.score.pnts, (255, 255, 255), self.f24)
  1195. pntsnrect = pntsnsurf.get_rect()
  1196. pntsnrect.right = self.SCREEN_WIDTH / 3 * 2
  1197. pntsnrect.centery = self.SCREEN_HEIGHT / 16 * 4
  1198. pntsnsurf.draw(pntsnrect.topleft)
  1199. deathsurf = pygl2d.font.RenderText("Deaths:", (255, 255, 0), self.f24)
  1200. deathrect = deathsurf.get_rect()
  1201. deathrect.left = self.SCREEN_WIDTH / 3
  1202. deathrect.centery = self.SCREEN_HEIGHT / 16 * 5.5
  1203. deathsurf.draw(deathrect.topleft)
  1204. deathnsurf = pygl2d.font.RenderText("%d" % (self.deaths), (255, 255, 255), self.f24)
  1205. deathnrect = deathnsurf.get_rect()
  1206. deathnrect.right = self.SCREEN_WIDTH / 3 * 2
  1207. deathnrect.centery = self.SCREEN_HEIGHT / 16 * 5.5
  1208. deathnsurf.draw(deathnrect.topleft)
  1209. cntrlsurf = pygl2d.font.RenderText("Destroyed fortresses:", (255, 255, 0), self.f24)
  1210. cntrlrect = cntrlsurf.get_rect()
  1211. cntrlrect.left = self.SCREEN_WIDTH / 3
  1212. cntrlrect.centery = self.SCREEN_HEIGHT / 16 * 7
  1213. cntrlsurf.draw(cntrlrect.topleft)
  1214. cntrlnsurf = pygl2d.font.RenderText("%d" % (self.destroyedFortresses), (255, 255, 255), self.f24)
  1215. cntrlnrect = cntrlnsurf.get_rect()
  1216. cntrlnrect.right = self.SCREEN_WIDTH / 3 * 2
  1217. cntrlnrect.centery = self.SCREEN_HEIGHT / 16 * 7
  1218. cntrlnsurf.draw(cntrlnrect.topleft)
  1219. vlctysurf = pygl2d.font.RenderText("Destroyed mines:", (255, 255, 0), self.f24)
  1220. vlctyrect = vlctysurf.get_rect()
  1221. vlctyrect.left = self.SCREEN_WIDTH / 3
  1222. vlctyrect.centery = self.SCREEN_HEIGHT / 16 * 8.5
  1223. vlctysurf.draw(vlctyrect.topleft)
  1224. vlctynsurf = pygl2d.font.RenderText("%d of %d" % (self.destroyedMines, self.totalMines), (255, 255, 255), self.f24)
  1225. vlctynrect = vlctynsurf.get_rect()
  1226. vlctynrect.right = self.SCREEN_WIDTH / 3 * 2
  1227. vlctynrect.centery = self.SCREEN_HEIGHT / 16 * 8.5
  1228. vlctynsurf.draw(vlctynrect.topleft)
  1229. speedsurf = pygl2d.font.RenderText("Captured bonuses:", (255, 255, 0), self.f24)
  1230. speedrect = speedsurf.get_rect()
  1231. speedrect.left = self.SCREEN_WIDTH / 3
  1232. speedrect.centery = self.SCREEN_HEIGHT / 16 * 10
  1233. speedsurf.draw(speedrect.topleft)
  1234. speednsurf = pygl2d.font.RenderText("%d of %d" % (self.capturedBonuses, self.totalBonuses), (255, 255, 255), self.f24)
  1235. speednrect = speednsurf.get_rect()
  1236. speednrect.right = self.SCREEN_WIDTH / 3 * 2
  1237. speednrect.centery = self.SCREEN_HEIGHT / 16 * 10
  1238. speednsurf.draw(speednrect.topleft)
  1239. pygl2d.draw.line((self.SCREEN_WIDTH / 4 , self.SCREEN_HEIGHT / 16 * 11), (self.SCREEN_WIDTH / 4 * 3, self.SCREEN_HEIGHT / 16 * 11), (255, 255, 255))
  1240. if self.current_game == self.config['General']['games_per_session']:
  1241. finalsurf = pygl2d.font.RenderText("You're done! Press return to exit", (0, 255, 0), self.f24)
  1242. else:
  1243. finalsurf = pygl2d.font.RenderText("Press return for next game", (0, 255, 0), self.f24)
  1244. finalrect = finalsurf.get_rect()
  1245. finalrect.centerx = self.SCREEN_WIDTH / 2
  1246. finalrect.centery = self.SCREEN_HEIGHT / 16 * 14
  1247. finalsurf.draw(finalrect.topleft)
  1248. def draw_new_score(self):
  1249. """shows score for last game and waits to continue"""
  1250. pygame.event.get() #clear event list? Otherwise it skips
  1251. self.screen.fill((0, 0, 0))
  1252. #sessionsurf = self.f24.render("Session %d, Game %d/%s"%(self.session_number, self.game_number, self.config["games_per_session"]), True, (255,255,255))
  1253. # sessionrect = sessionsurf.get_rect()
  1254. # sessionrect.centerx = self.SCREEN_WIDTH / 2
  1255. # sessionrect.y = 100
  1256. # self.screen.blit(sessionsurf, sessionrect)
  1257. gamesurf = self.f36.render("Game %d" % (self.current_game), True, (255, 255, 0))
  1258. gamerect = gamesurf.get_rect()
  1259. gamerect.centery = self.SCREEN_HEIGHT / 16 * 2
  1260. gamerect.centerx = self.SCREEN_WIDTH / 2
  1261. self.screen.blit(gamesurf, gamerect)
  1262. pygame.draw.line(self.screen, (255, 255, 255), (self.SCREEN_WIDTH / 4 , self.SCREEN_HEIGHT / 16 * 3), (self.SCREEN_WIDTH / 4 * 3, self.SCREEN_HEIGHT / 16 * 3))
  1263. pntssurf = self.f24.render("Flight score:", True, (255, 255, 0))
  1264. pntsrect = pntssurf.get_rect()
  1265. pntsrect.left = self.SCREEN_WIDTH / 3
  1266. pntsrect.centery = self.SCREEN_HEIGHT / 16 * 4
  1267. self.screen.blit(pntssurf, pntsrect)
  1268. cntrlsurf = self.f24.render("Fortress score:", True, (255, 255, 0))
  1269. cntrlrect = cntrlsurf.get_rect()
  1270. cntrlrect.left = self.SCREEN_WIDTH / 3
  1271. cntrlrect.centery = self.SCREEN_HEIGHT / 16 * 6
  1272. self.screen.blit(cntrlsurf, cntrlrect)
  1273. vlctysurf = self.f24.render("Mine score:", True, (255, 255, 0))
  1274. vlctyrect = vlctysurf.get_rect()
  1275. vlctyrect.left = self.SCREEN_WIDTH / 3
  1276. vlctyrect.centery = self.SCREEN_HEIGHT / 16 * 8
  1277. self.screen.blit(vlctysurf, vlctyrect)
  1278. speedsurf = self.f24.render("Bonus score:", True, (255, 255, 0))
  1279. speedrect = speedsurf.get_rect()
  1280. speedrect.left = self.SCREEN_WIDTH / 3
  1281. speedrect.centery = self.SCREEN_HEIGHT / 16 * 10
  1282. self.screen.blit(speedsurf, speedrect)
  1283. pntsnsurf = self.f24.render("%d" % self.score.flight, True, (255, 255, 255))
  1284. pntsnrect = pntsnsurf.get_rect()
  1285. pntsnrect.right = self.SCREEN_WIDTH / 3 * 2
  1286. pntsnrect.centery = self.SCREEN_HEIGHT / 16 * 4
  1287. self.screen.blit(pntsnsurf, pntsnrect)
  1288. cntrlnsurf = self.f24.render("%d" % self.score.fortress, True, (255, 255, 255))
  1289. cntrlnrect = cntrlnsurf.get_rect()
  1290. cntrlnrect.right = self.SCREEN_WIDTH / 3 * 2
  1291. cntrlnrect.centery = self.SCREEN_HEIGHT / 16 * 6
  1292. self.screen.blit(cntrlnsurf, cntrlnrect)
  1293. vlctynsurf = self.f24.render("%d" % self.score.mines, True, (255, 255, 255))
  1294. vlctynrect = vlctynsurf.get_rect()
  1295. vlctynrect.right = self.SCREEN_WIDTH / 3 * 2
  1296. vlctynrect.centery = self.SCREEN_HEIGHT / 16 * 8
  1297. self.screen.blit(vlctynsurf, vlctynrect)
  1298. speednsurf = self.f24.render("%d" % self.score.bonus, True, (255, 255, 255))
  1299. speednrect = speednsurf.get_rect()
  1300. speednrect.right = self.SCREEN_WIDTH / 3 * 2
  1301. speednrect.centery = self.SCREEN_HEIGHT / 16 * 10
  1302. self.screen.blit(speednsurf, speednrect)
  1303. #draw line
  1304. pygame.draw.line(self.screen, (255, 255, 255), (self.SCREEN_WIDTH / 4 , self.SCREEN_HEIGHT / 16 * 11), (self.SCREEN_WIDTH / 4 * 3, self.SCREEN_HEIGHT / 16 * 11))
  1305. totalsurf = self.f24.render("Total game score:", True, (255, 255, 0))
  1306. totalrect = totalsurf.get_rect()
  1307. totalrect.left = self.SCREEN_WIDTH / 3
  1308. totalrect.centery = self.SCREEN_HEIGHT / 16 * 12
  1309. self.screen.blit(totalsurf, totalrect)
  1310. totalnsurf = self.f24.render("%d" % (self.score.flight + self.score.fortress + self.score.mines + self.score.bonus), True, (255, 255, 255))
  1311. totalnrect = totalnsurf.get_rect()
  1312. totalnrect.right = self.SCREEN_WIDTH / 3 * 2
  1313. totalnrect.centery = self.SCREEN_HEIGHT / 16 * 12
  1314. self.screen.blit(totalnsurf, totalnrect)
  1315. if self.current_game == self.config['General']['games_per_session']:
  1316. finalsurf = self.f24.render("You're done! Press return to exit", True, (0, 255, 0))
  1317. else:
  1318. finalsurf = self.f24.render("Press return for next game", True, (0, 255, 0))
  1319. finalrect = finalsurf.get_rect()
  1320. finalrect.centerx = self.SCREEN_WIDTH / 2
  1321. finalrect.centery = self.SCREEN_HEIGHT / 16 * 14
  1322. self.screen.blit(finalsurf, finalrect)
  1323. def init_stars(self):
  1324. """ Create the starfield """
  1325. self.stars = []
  1326. for i in range(self.config['Graphics']['max_stars']):
  1327. star = [randrange(self.world.left, self.world.right),
  1328. randrange(self.world.top, self.world.bottom),
  1329. choice([1, 2, 3])]
  1330. self.stars.append(star)
  1331. def draw_kp(self):
  1332. color = (48, 48, 48)
  1333. left = self.WORLD_WIDTH / 2 - self.WORLD_WIDTH / 12
  1334. top = self.WORLD_HEIGHT - self.WORLD_HEIGHT / 18 * 2
  1335. width = self.WORLD_WIDTH / 12 * 2
  1336. height = self.WORLD_HEIGHT / 18 * .75
  1337. pygame.draw.rect(self.worldsurf, color, (left, top, width, height), self.kp_space)
  1338. top = top - height * 1.5
  1339. left = left + width + height / 2
  1340. width = height
  1341. pygame.draw.rect(self.worldsurf, color, (left, top, width, height), self.kp_iff)
  1342. left = left + width + height / 2
  1343. pygame.draw.rect(self.worldsurf, color, (left, top, width, height), self.kp_shots)
  1344. left = left + width + height / 2
  1345. pygame.draw.rect(self.worldsurf, color, (left, top, width, height), self.kp_points)
  1346. left = self.WORLD_WIDTH / 2 - self.WORLD_WIDTH / 12 - width - height / 2
  1347. pygame.draw.rect(self.worldsurf, color, (left, top, width, height), self.kp_right)
  1348. left = left - width - height / 2
  1349. top = top - height * 1.5
  1350. pygame.draw.rect(self.worldsurf, color, (left, top, width, height), self.kp_thrust)
  1351. left = left - width - height / 2
  1352. top = top + height * 1.5
  1353. pygame.draw.rect(self.worldsurf, color, (left, top, width, height), self.kp_left)
  1354. def draw_complete(self):
  1355. fpssurf = self.f96.render("Session Complete", True, (255, 0, 0))
  1356. fpsrect = fpssurf.get_rect()
  1357. fpsrect.centerx = self.SCREEN_WIDTH / 2
  1358. fpsrect.centery = self.SCREEN_HEIGHT / 2
  1359. self.screen.blit(fpssurf, fpsrect)
  1360. def quit(self, lc):
  1361. self.gameevents.add("game", "quit", self.ret, type='EVENT_USER')
  1362. if self.ret == 0:
  1363. self.gameevents.add("session", "complete", type='EVENT_SYSTEM')
  1364. else:
  1365. self.gameevents.add("session", "incomplete", type='EVENT_SYSTEM')
  1366. self.process_events()
  1367. if self.config['Logging']['logging']:
  1368. self.log.close()
  1369. if self.ret == 0:
  1370. os.rename(self.log_filename, self.log_filename[:-11])
  1371. pygame.quit()
  1372. self.reactor.stop()
  1373. def draw_scores(self, time=0):
  1374. self.gameevents.add("game", "end", type='EVENT_SYSTEM')
  1375. self.gameevents.add("scores", "show", type='EVENT_SYSTEM')
  1376. if self.config['General']['next_gen']:
  1377. self.draw_ng_score(time)
  1378. elif self.config['Score']['new_scoring']:
  1379. self.draw_new_score()
  1380. else:
  1381. self.draw_old_score()
  1382. self.gameevents.add("scores", "hide", type='EVENT_SYSTEM')
  1383. def refresh(self):
  1384. if self.state != self.STATE_CALIBRATE:
  1385. self.process_input()
  1386. self.process_events()
  1387. self.process_game_logic()
  1388. self.draw()
  1389. if self.config['Logging']['logging'] and self.config['Logging']['logDriver'] == 'Default':
  1390. self.log_world()
  1391. def start(self):
  1392. self.lc = LoopingCall(self.refresh)
  1393. cleanupD = self.lc.start(1.0 / self.fps)
  1394. cleanupD.addCallbacks(self.quit)
  1395. def run(self):
  1396. reactor.callLater(0, self.start)
  1397. reactor.run()

game.py at commit 710e123, no license · at the source

Overview

Authors: Anneke Hamann1, Julia Schön1, Nils Carstengerdes1
  1. Institut für Flugführung, Deutsches Zentrum für Luft- und Raumfahrt e.V. (DLR), Braunschweig, Germany
Journal: Frontiers in neuroergonomics, volume 7, article 1894934
Dates: received 29 May 2026; accepted 31 August 2026; published online 23 September 2026
Type: Research article · Language: English
License: CC BY
Identifiers: DOI · PMCID PMC13642727
Status: code verified (how the code is found and verified)
Categories: EEG (modality), human (organism), cognitive (subfield)
Methods: Spectral & time-frequency, Preprocessing, Smoothing, state filtering, decompositions, Statistics, Physiology & signal measures
Keywords: aviation, cross-task performance prediction, EEG, mental workload, n-back, operator state, Space Fortress Game, training
Citations: not cited yet (Europe PMC); 68 references in the paper

Abstract

In recent years, operator state assessment has gained much attention in the aviation domain. The ability to assess or even predict performance from behavioral or physiological data offers the possibility to tailor training schedules and assistance systems to the human operators' needs. Yet, to date, there is still no valid or reliable method for such an assessment. In the present study, we present evidence that brain activity recorded via electroencephalography (EEG) can be used to predict complex cognitive task performance. 26 participants performed multiple rounds of a dual n-back task and the complex Space Fortress Game while their brain activity was recorded via EEG. Results from multiple linear regression analyses indicate that Space Fortress Game performance could be predicted reasonably well from EEG Power Spectral Density parameters from the same game, a previous game and from the dual n-back task. Our findings show that it is possible to use data from task training and even from dissimilar, less complex tasks to predict complex task performance (in offline analyses after data collection). They also underline the utility of using EEG measurements for operator state monitoring.

Reproduced under the paper's license (CC BY), from the paper cited above.

Repository

Its files are read in the Code ↔ Paper reader above, with 1 match between paragraphs and lines of code.

CogWorks/SpaceFortress

License: none: the authors keep all their rights
State: the link answers, verified on 8 October 2026
Evidence: files inventoried
Commit: 710e12302e8adbdda597ff29f686324804fbf294, 3 March 2015
Languages: Python (27)
Size: 68 files, 27 scripts
Software Heritage: not archived
Found in: the text, “Space Fortress Game”
Holds: README, documentation
Not found: license file, CITATION.cff, environment file, tests, continuous integration
Tools: NumPy (2 files)
Availability: 1 check, the latest on 8 October 2026: the link answers
  • 8 October 2026: the link answers
28 files

Tracing map

Proposed by the machine: these links were found in the paper and verified at the source, without human review. The map will receive a Zenodo DOI once one of the paper's authors has validated it with their ORCID.

What the map holds:

  • 1 repository of the authors' code, each at its verified commit, with its license and how the link was found in the paper;
  • 27 scripts, each with its path and the digest of its content;
  • 1 match between paragraphs of the paper and lines of the code (method lexical-v1);
  • neither the text of the paper nor the code itself.

Its JSON (tracing-map.json) is deposited on Zenodo with its DOI once the map is validated.

Data

No dataset and no data link were found in the paper.

Data availability statement

The raw data supporting the conclusions of this article will be made available by the authors, without undue reservation.

Reproduced under the paper's license (CC BY), from the paper cited above.

Versions

The history of this record: each version stored by the harvester or made by a correction of its authors or of the maintainers of its code, and what changed in its facts. The texts of the paper (its abstract, its availability statements) are not part of it; versions that changed only those are not listed.

Version 1, 8 October 2026: the first record

Recorded: type, language, journal, volume, pages, dates, 3 authors, 8 keywords, 62 references.

Cite

This paper

Hamann, A., Schön, J., & Carstengerdes, N. (2026). I think, therefore I hit: EEG parameters predict performance in complex cognitive tasks. Frontiers in neuroergonomics, 7, 1894934.

BibTeX

@article{hamann2026i,
author = {Hamann, Anneke and Schön, Julia and Carstengerdes, Nils},
title = {{I think, therefore I hit: EEG parameters predict performance in complex cognitive tasks}},
journal = {Frontiers in neuroergonomics},
year = {2026},
month = oct,
volume = {7},
pages = {1894934},
publisher = {Frontiers Media SA},
issn = {2673-6195},
pmcid = {PMC13642727}
}

RIS

TY - JOUR
AU - Hamann, Anneke
AU - Schön, Julia
AU - Carstengerdes, Nils
TI - I think, therefore I hit: EEG parameters predict performance in complex cognitive tasks
T2 - Frontiers in neuroergonomics
J2 - Front Neuroergon
PY - 2026
DA - 2026/10/08
VL - 7
SP - 1894934
SN - 2673-6195
PB - Frontiers Media SA
LA - en
ER -

CSL-JSON

{
"id": "pmcid:PMC13642727",
"type": "article-journal",
"title": "I think, therefore I hit: EEG parameters predict performance in complex cognitive tasks",
"container-title": "Frontiers in neuroergonomics",
"author": [
{
"family": "Hamann",
"given": "Anneke"
},
{
"family": "Schön",
"given": "Julia"
},
{
"family": "Carstengerdes",
"given": "Nils"
}
],
"container-title-short": "Front Neuroergon",
"volume": "7",
"page": "1894934",
"PMCID": "PMC13642727",
"ISSN": "2673-6195",
"publisher": "Frontiers Media SA",
"language": "en",
"issued": {
"date-parts": [
[
2026,
10,
8
]
]
}
}

The tracing map gets a citation of its own once an author has validated it and it has a DOI.

Similar papers

The papers with a page that share the most with this one: the tools found in their code, their categories, datasets, cited references and authors, the rarest counting most.

[1] doi:10.3389/fphys.2026.1893570
Examining physiological parameters of mental workload in the cockpit: a multimethod approach.
Journal: Frontiers in physiology
In common: 9 references
[2] doi:10.3389/fnrgo.2022.1007673 [code]
Predictions of task using neural modeling.
Journal: Frontiers in neuroergonomics
In common: NumPy, EEG, cognitive, 4 references
[3] doi:10.1111/ejn.70283 [code]
Shielding the Mind With Flow: Attention Allocation and Auditory Event-Related Potentials Under Varying Mental Workload.
Journal: The European journal of neuroscience
In common: EEG, cognitive, 3 references
[4] doi:10.1016/j.isci.2026.114757 [code]
Decoding P300 as a shared neural mechanism for oddball target detection and working memory updating.
Journal: iScience
In common: EEG, cognitive, 3 references
[5] doi:10.1038/s42003-023-05168-4 [code]
Comparative analysis of multifaceted neural effects associated with varying endogenous cognitive load.
Journal: Communications biology
In common: NumPy, EEG, cognitive, 2 references
[6] doi:10.1038/s41598-025-90540-z
Effects of startle on cognitive performance and physiological activity revealed by fNIRS and thermal imaging.
Journal: Scientific reports
In common: cognitive, 3 references
[7] doi:10.1038/s41467-024-52541-w [code]
Maintenance and transformation of representational formats during working memory prioritization.
Journal: Nature communications
In common: NumPy, EEG, cognitive, 2 references
[8] doi:10.1038/s41598-023-31264-w [code]
Assessing the development of mental fatigue during simulated flights with concurrent EEG-fNIRS measurement.
Journal: Scientific reports
In common: EEG, 2 references
[9] doi:10.1016/j.neuroimage.2026.121718 [code]
Frontotemporal bursting supports human working memory.
Journal: NeuroImage
In common: NumPy, cognitive, 2 references
[10] doi:10.1038/s41467-026-73818-2 [code]
Prefrontal parvalbumin neurons mediate working memory in a task demand-dependent manner.
Journal: Nature communications
In common: NumPy, cognitive, 2 references

Contribute

The authors of this paper can claim it, correct its record and validate its tracing map, and the maintainers of its code (its owner, or a public member of its organization) correct what it says of their repository; anyone signed in can ask for its removal. Every request goes to OSCR's own machine, which answers it; your account page follows them.

Sign in with ORCID to claim this paper as one of its authors, correct its record or validate its tracing map: when the paper's metadata lists your ORCID iD, you are recognized at once. Maintainers of its code: sign in with GitHub, then claim the repository on your account page.

Add the badge to the code's README

OSCR: the badge of this paper

If you are an author or a maintainer of this paper's code, you can add this badge. It says what OSCR knows of the paper (its code, its validated tracing map) and links the code to this page. Paste one of these snippets under the README's title. Keep the two marks around it, so that the badge can be replaced in place and is never added twice. OSCR changes nothing in your repository.

Markdown
<!-- oscr-badge:start -->
[![OSCR](https://openscicode.org/badge/repo/github.com/cogworks/spacefortress.svg)](https://openscicode.org/badge/repo/github.com/cogworks/spacefortress)
<!-- oscr-badge:end -->
reStructuredText
.. oscr-badge:start

.. image:: https://openscicode.org/badge/repo/github.com/cogworks/spacefortress.svg
   :target: https://openscicode.org/badge/repo/github.com/cogworks/spacefortress
   :alt: OSCR

.. oscr-badge:end
HTML
<!-- oscr-badge:start -->
<a href="https://openscicode.org/badge/repo/github.com/cogworks/spacefortress"><img src="https://openscicode.org/badge/repo/github.com/cogworks/spacefortress.svg" alt="OSCR"></a>
<!-- oscr-badge:end -->

On GitHub, open the README, choose Edit (the pencil), paste the snippet under the title, then "Commit changes".

If you choose to, you can have the badge kept up to date for you, with oscr badge --write from the command line or with the GitHub Action in your repository's workflows. Every other form and option (a card, AsciiDoc, LaTeX, shields.io) is on the badge page.

Request its removal

To ask OSCR to remove this record, the copies of its authors' scripts or its tracing map, use the removal request page: signed in, you say who you are, what to remove and why, then review and confirm the request. Published rules decide every request (how).

Discussion, reproductions, activity

Discussion: code errors and mismatches between the code and the paper about this paper and its code, from readers and its authors, beside the paper and its tracing map.

Report a mismatch between the code and the paper · Report a code error (signed in)

Reproductions: reports from readers who ran the authors' code and did not get the paper's result, what they ran, with which environment, commit and data.

Report a reproduction failure (signed in)

Versions of its code: the releases of its code tied to a version of this paper (the preprint, the accepted manuscript, the version of record…), each with the tracing map versioned with it.

Activity: what happens around this paper: new versions of its record, its map's validation, discussions and reproductions. It opens with sign-in.