from .game_objects import GameObject#, NoObject
from ._helper_methods import _convert_number
import sys
"""
RAM extraction for the game KANGUROO. Supported modes: ram.
"""
MAX_NB_OBJECTS = {'Player': 1, 'Player_Projectile':1, 'Torpedos': 1} # Asteroid count can get really high
MAX_NB_OBJECTS_HUD = {'Life': 1, 'HUD': 1}
[docs]
class Player(GameObject):
"""
The player figure i.e., the space ship.
"""
def __init__(self):
super(Player, self).__init__()
self.visible = True
self._xy = 77, 167
self.wh = 15, 13
self.rgb = 210, 210, 64
self.hud = False
[docs]
class Player_Projectile(GameObject):
"""
The laser lariats that can be fired from the space ship.
"""
def __init__(self):
super().__init__()
self.rgb = 198, 108, 58
[docs]
class Torpedos(GameObject):
"""
The limited torpedoes that can be fired from the space ship.
"""
def __init__(self):
super().__init__()
self.rgb = 164, 89, 208
[docs]
class Saucer(GameObject):
"""
The White Enemy Saucers.
"""
def __init__(self):
super().__init__()
self.visible = True
self._xy = 0, 0
self.wh = 8, 5
self.rgb = 236, 236, 236
self.hud = False
[docs]
class Rejuvenator(GameObject):
"""
The Yellow Rejuvinators occasionally floating through the beam matrix.
"""
def __init__(self):
super().__init__()
self.rgb = 187, 187, 53
[docs]
class Sentinel(GameObject):
"""
The Sector Sentinel Ship, which appears once a sector has been cleared.
"""
def __init__(self):
super().__init__()
self.rgb = 184, 50, 50
[docs]
class Blocker(GameObject):
"""
The Green Blocker Ships (sector 6).
"""
def __init__(self):
super().__init__()
self.rgb = 135, 183, 84
[docs]
class Jumper(GameObject):
def __init__(self):
super().__init__()
self.rgb = None
[docs]
class Charger(GameObject):
"""
The Blue Chargers (sector 10).
"""
def __init__(self):
super().__init__()
self.rgb = None
[docs]
class Bouncecraft(GameObject):
"""
The Green Bounce Craft (sector 8).
"""
def __init__(self):
super().__init__()
self.rgb = None
[docs]
class Chriper(GameObject):
"""
The Yellow Chirper Ships (sector 4).
"""
def __init__(self):
super().__init__()
self.rgb = None
[docs]
class Rock(GameObject):
"""
The Brown Space Debris (sector 2).
"""
def __init__(self):
super().__init__()
self.rgb = 134, 134, 29
[docs]
class Torpedos_Available(GameObject):
"""
The torpedoe availability display.
"""
def __init__(self):
super().__init__()
self.rgb = 104, 25, 154
[docs]
class Enemy_Projectile(GameObject):
"""
Enemy projectiles.
"""
def __init__(self):
super().__init__()
self.rgb = 164, 89, 208
[docs]
class HUD(GameObject):
def __init__(self):
super().__init__()
self.rgb = 210, 164, 74
[docs]
class Enemy_Amount(GameObject):
"""
The count display for the remaining Enemy Saucers in the current sector.
"""
def __init__(self):
super().__init__()
self.rgb = 82, 126, 45
[docs]
class Life(GameObject):
"""
The lives-indicator of the player.
"""
def __init__(self):
super().__init__()
self.rgb = 210, 210, 64
def _get_max_objects(hud=False):
def fromdict(max_obj_dict):
objects = []
mod = sys.modules[__name__]
for k, v in max_obj_dict.items():
for _ in range(0, v):
objects.append(getattr(mod, k)())
return objects
if hud:
return fromdict(MAX_NB_OBJECTS_HUD)
return fromdict(MAX_NB_OBJECTS)
def _init_objects_ram(hud=True):
"""
(Re)Initialize the objects
"""
objects = [Player()] + [None]*7
return objects
# levels: ram_state[36], total of 3 levels: 0,1 and 2
def _detect_objects_ram(objects, ram_state, hud=True):
player = objects[0]
player.xy = int(ram_state[41]*1.5)-115, 167
y_positions = ram_state[25:32]
state_positions = range(0, 7)
y_positions = [y_pos for y_pos in y_positions if y_pos < 255]
y_positions = list(zip(y_positions, state_positions))
y_positions.sort(reverse=True)
# print(y_positions)
# The x pos of the center line has the RAM value 128, that translates to 80 (gained from using the pure number value of the hex value, works like the score)
# When enemies move forward, their position moves further outwards, while the RAM stays the same
# Enemies always move down one of the lines, if they are not at the top
# lanes from left to right
# 1 2 3 4 5 6 7
# 60 94 111 128 145 162 196
for i in range(7):
if ram_state[33+i] != 0:
# print(_convert_number(ram_state[33+i]), ram_state[33+i])
x = ram_state[33+i]
res_x = _convert_number(ram_state[33+i])
if res_x is None:
if x < 154:
new_x = (x|15) + 1
res_x = _convert_number(new_x)
else:
x+=96
res_x = _convert_number(x)
if res_x is None:
new_x = (x|15) + 1
res_x = _convert_number(new_x)
y_pos = [x for x, y in enumerate(y_positions) if y[1] == i]
if len(y_pos):
y = 165 - ram_state[95-y_pos[0]]
else:
y = 43
# x position has an outwards drift from 80 (center line)
# drift is exponential, these linear ones don't work
#
# if res_x < 80:
# res_x = res_x+i - ((y-43)>>2)
# else:
# res_x = res_x+i + ((y-43)>>2)
# print(y_pos, y_positions)
enemy = Saucer()
enemy.xy = res_x, y
enemy.wh = 2, 2
objects[1+i] = enemy
def _detect_objects_beamrider_raw(info, ram_state):
player_x = ram_state[41]
enemy_x = ram_state[33:40]
enemy_y = ram_state[25:32]
projectile_x = ram_state[40]
projectile_y = ram_state[32]
# ram_state[42:49]no clue? kills player
# ram_state[49] projectile; 0 shootable, 35 already shot
# ram_state[0] sector
# ram_state[5] lives: renders up to 13
# ram_state[16] gamestatus: 1 = neutral, 2 = fighting, 3 = sentinel, 4 = transition
# ram_state[83] torpedo amount
# ram_state[83] enemy amount
# 93-95 irgend was mit entfernung von Gegnern. 93 am weitesten entfernt 95 am nächsten
return player_x + enemy_x, enemy_y + projectile_x, projectile_y
def _get_x_position(ramstate):
"""
converts the x Position in the RAM to the proper Position on screen
"""
pos = 26
for i in range(ramstate-94):
if i % 2 == 0:
pos = pos+1
else:
pos = pos+2
return pos