Question
Task 1: Basic Hubo Snake Goal The goal of Task 1 is to implement Snake game using Hubo according to the rules described in Section
Task 1: Basic Hubo Snake
Goal
The goal of Task 1 is to implement Snake game using Hubo according to the rules described in Section 2.2 of the document. Specifically, you should complete class Snake and SnakeGame. Please read the document carefully. Make sure you have understood it thoroughly before working on an implementation.
Restrictions
You must use cs1games library not cs1robots. (See Section A.1)
You can add your own functions or variables if you want, but all functions and variables you added must be included in the given classes. No global variables or functions are allowed.
Suggested Order of Implementation
Implement class Snake, and create a Snake object in __init__ of SnakeGame.
Complete the function is_occupied.
Call generate_food in the constructor of SnakeGame.
Make the game playable with 1-length-snake.
Implement control so that the snake can turn according to a key input.
Implement next_step so that 1-length-snake can move forward.
Check the end condition. When the the end condition is reached, call gameover.
Implement the case when the snake reaches to the food. Extend the snake and generate a new food with generate_food.
Update your implementation so that an extended snake can move. This is a substantial upgrade from a 1-length-snakecase, so it will take some time.
Complete the function score.
cs1games.py
Environment for a game design homework.
Hubo will be used as a game resource.
*****************************
** DO NOT MODIFY THIS FILE **
*****************************
"""
import random
from abc import ABC, abstractmethod
from threading import Lock
from copy import deepcopy
import cs1robots as _robots
# CONSTANTS
# ---------
SIZE = 10
TIMER_KEY = 'timer'
TIMER_PERIOD = 300
AI_TIMER_PERIOD = 1
_ROBOTS = []
# WORLD CONTROL
# -------------
_SCENE = None # _robots._scene
_WORLD = None # _robots._world
def redraw():
if _SCENE:
_SCENE.refresh()
def random_number(lessthan):
"""Returns a random integer number in 0 ~ (lessthan - 1)"""
return random.randrange(lessthan)
# MODIFY CS1ROBOTS
# ----------------
class Robot(_robots.Robot):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
_ROBOTS.append(self)
def _refresh(self):
pass
def set_pos(self, avenue, street):
"""Locate the robot at (avenue, street)."""
self._x = avenue
self._y = street
self._update_pos()
self._update_trace()
self._refresh()
def set_orientation(self, orientation):
"""Set the orientation of the robot as orientation (e.g., N, S, W,
E)."""
self._image[self._dir].moveTo(-100, -100)
self._dir = _robots._orient_dict[orientation]
self._update_pos()
self._update_trace()
self._refresh()
def set_color(self, color):
"""Set the color of the robot as color."""
for i in range(4):
_SCENE.remove(self._image[i])
for i in range(4):
self._image[i] = _robots._g.Image(
"base64:" + _robots._robot_images[color][i])
self._image[i].moveTo(-100, -100)
self._image[i].setDepth(0)
_SCENE.add(self._image[i])
self._update_pos()
self._refresh()
def remove(self):
"""Remove the robot from the world.
You should not call any function of this object after remove() is
called."""
_ROBOTS.remove(self)
for i in range(4):
self._image[i].moveTo(-100, -100)
# GAME CLASSES
# ------------
class Game(ABC):
def __init__(self):
global _SCENE, _WORLD # pylint: disable=global-statement
_robots.create_world(avenues=SIZE, streets=SIZE)
_SCENE = _robots._scene
_WORLD = _robots._world
self.finished = False
self.control_lock = Lock()
self.control_q = []
def __del__(self):
global _SCENE, _WORLD # pylint: disable=global-statement
_WORLD = None
_SCENE = None
if _robots._world:
_robots._world = None
if _robots._scene and _robots._scene._canvasOpen:
_robots._scene.close()
_robots._scene = None
@abstractmethod
def control(self, key):
pass
@abstractmethod
def next_step(self):
pass
def state(self):
pass
def score(self):
pass
def gameover(self):
"""Stops the game and prints the score of final state.
You must call this when your game should be over."""
if self.finished:
return
self.finished = True
print("### Game Over ###")
print("- Score: {}".format(self.score()))
def play(self):
"""Starts the game. You can play the game by pressing keys.
The game will last until gameover is called or when you press q."""
self._register_timer()
while not self.finished:
e = _SCENE.wait()
if e and e.getDescription() == "keyboard":
k = e.getKey()
if k == 'q':
break
else:
self._emit(k)
_SCENE.close()
def play_step(self):
"""This function is same to play except it continues to next step only
when you press an enter key.
You can have enough time to think about the execution of your program
and then press enter to test a next step.
This can be useful for debugging your program."""
while not self.finished:
e = _SCENE.wait()
if e and e.getDescription() == "keyboard":
k = e.getKey()
if k == 'q':
break
elif k in [' ', ' ']:
self._emit(TIMER_KEY)
else:
self._emit(k)
_SCENE.close()
def play_ai(self, *ai):
self._register_ai_emulator(lambda: self._emulate_ai(ai))
while True:
if self.finished:
break
e = _SCENE.wait()
if e and e.getDescription() == "keyboard":
k = e.getKey()
if k == 'q':
break
_SCENE.close()
def play_ai_step(self, *ai):
while True:
if self.finished:
break
e = _SCENE.wait()
if e and e.getDescription() == "keyboard":
k = e.getKey()
if k == 'q':
break
elif k in [' ', ' ']:
self._emulate_ai(ai)
_SCENE.close()
def _emulate_ai(self, ais):
state = deepcopy(self.state())
self._emit(ais[0](*state))
self._emit(TIMER_KEY)
def _emit(self, key):
if self.control_lock.acquire(blocking=False):
try:
self.control_q.append(key)
while self.control_q:
key = self.control_q.pop(0)
if key == TIMER_KEY:
self.next_step()
redraw()
else:
self.control(key)
redraw()
finally:
self.control_lock.release()
else:
self.control_q.append(key)
def _register_timer(self):
def f(_):
if not self.finished:
self._emit(TIMER_KEY)
_SCENE.addPeriodicHandler(TIMER_PERIOD, f)
def _register_ai_emulator(self, emulator):
def f(_):
if not self.finished:
emulator()
_SCENE.addPeriodicHandler(AI_TIMER_PERIOD, f)
class PvPGame(Game):
def gameover(self, win_player=-1): # pylint: disable=arguments-differ
"""Stops the game and prints the score of final state.
You must call this when your game should be over."""
if self.finished:
return
self.finished = True
print("### Game Over ###")
if win_player == 0:
print("Draw!")
elif win_player > 0:
print("Player {} win!".format(win_player))
def _emulate_ai(self, ais):
def convert_key(ai):
from functools import wraps
KEYS1 = ['w', 'a', 's', 'd']
KEYS2 = ['i', 'j', 'k', 'l']
@wraps(ai)
def _ai(food_pos, snake1_state, snake2_state):
return KEYS2[KEYS1.index(ai(food_pos, snake2_state, snake1_state))]
return _ai
state1 = deepcopy(self.state())
state2 = deepcopy(self.state())
self._emit(ais[0](*state1))
self._emit(convert_key(ais[1])(*state2))
self._emit(TIMER_KEY)
Step by Step Solution
There are 3 Steps involved in it
Step: 1
Get Instant Access to Expert-Tailored Solutions
See step-by-step solutions with expert insights and AI powered tools for academic success
Step: 2
Step: 3
Ace Your Homework with AI
Get the answers you need in no time with our AI-driven, step-by-step assistance
Get Started