import sys, random, pygame
pygame.init()
pygame.font.init()
# Setup grid & display settings
GRID_SIZE, CELL_SIZE = 8, 60
OFF_X, OFF_Y = 160, 60
W, H = 800, 650
SCREEN = pygame.display.set_mode((W, H))
pygame.display.set_caption("Grounded Language: Grid Pointing Game")
CLOCK = pygame.time.Clock()
FONT_MAIN = pygame.font.SysFont("Arial", 20, bold=True)
FONT_UI = pygame.font.SysFont("Arial", 16)
# Colors: BG, Grid, Obstacle, Box BG, Box Border, Text, Success, Error
C_BG, C_GRID, C_OBS = (240, 243, 246), (180, 185, 190), (100, 110, 120)
C_BOX_BG, C_BOX_BDR, C_TXT = (220, 225, 230), (140, 150, 160), (30, 40, 50)
C_SUCC, C_ERR = (46, 204, 113), (231, 76, 60)
# 2x2 Obstacle cells in the middle
OBSTACLE_CELLS = {(3, 3), (3, 4), (4, 3), (4, 4)}
ACTIONS = ["point at", "click on", "select", "target"]
class PointingGame:
def __init__(self):
self.score = 0
self.fb_msg, self.fb_col, self.fb_timer = "", C_TXT, 0
self.new_quest()
def new_quest(self):
act = random.choice(ACTIONS)
qtype = random.choice(["specific", "obstacle", "top", "bottom", "left", "right"])
if qtype == "specific":
x, y = random.randint(0, 7), random.randint(0, 7)
self.quest = f'NPC Quest: "{act} ({x},{y})"'
self.check = lambda cx, cy, x=x, y=y: (cx, cy) == (x, y)
elif qtype == "obstacle":
self.quest = f'NPC Quest: "{act} the obstacle"'
self.check = lambda cx, cy: (cx, cy) in OBSTACLE_CELLS
else: # Top, Bottom, Left, or Right edge (8 cells each)
self.quest = f'NPC Quest: "{act} {qtype} edge cells"'
edges = {
"top": lambda cx, cy: cy == 0,
"bottom": lambda cx, cy: cy == 7,
"left": lambda cx, cy: cx == 0,
"right": lambda cx, cy: cx == 7
}
self.check = edges[qtype]
def handle_click(self, pos):
mx, my = pos
if OFF_X <= mx < OFF_X + 480 and OFF_Y <= my < OFF_Y + 480:
cx, cy = (mx - OFF_X) // CELL_SIZE, (my - OFF_Y) // CELL_SIZE
if self.check(cx, cy):
self.score += 10
self.fb_msg, self.fb_col = f"Correct! +10 pts for cell ({cx},{cy})", C_SUCC
self.new_quest()
else:
self.score = max(0, self.score - 5)
self.fb_msg, self.fb_col = f"Wrong! Cell ({cx},{cy}) is not the target. (-5)", C_ERR
self.fb_timer = pygame.time.get_ticks() + 1500
def draw(self):
SCREEN.fill(C_BG)
# Headers & Score
SCREEN.blit(FONT_MAIN.render("Grounded Language Grid Game", True, C_TXT), (OFF_X, 15))
SCREEN.blit(FONT_MAIN.render(f"Score: {self.score}", True, C_SUCC), (OFF_X + 320, 15))
# Axis Labels & Grid
mx, my = pygame.mouse.get_pos()
for i in range(8):
SCREEN.blit(FONT_UI.render(str(i), True, C_TXT), (OFF_X + i * 60 + 26, OFF_Y - 25))
SCREEN.blit(FONT_UI.render(str(i), True, C_TXT), (OFF_X - 25, OFF_Y + i * 60 + 22))
for cy in range(8):
for cx in range(8):
rect = pygame.Rect(OFF_X + cx * 60, OFF_Y + cy * 60, 60, 60)
col = C_OBS if (cx, cy) in OBSTACLE_CELLS else (255, 255, 255)
pygame.draw.rect(SCREEN, col, rect)
pygame.draw.rect(SCREEN, C_GRID, rect, 1)
if rect.collidepoint(mx, my):
s = pygame.Surface((60, 60), pygame.SRCALPHA)
s.fill((52, 152, 219, 100))
SCREEN.blit(s, rect.topleft)
# Quest & Feedback Widget
box = pygame.Rect(OFF_X - 40, OFF_Y + 505, 560, 85)
pygame.draw.rect(SCREEN, C_BOX_BG, box, border_radius=8)
pygame.draw.rect(SCREEN, C_BOX_BDR, box, width=2, border_radius=8)
SCREEN.blit(FONT_MAIN.render(self.quest, True, C_TXT), (box.x + 20, box.y + 15))
if pygame.time.get_ticks() < self.fb_timer:
SCREEN.blit(FONT_UI.render(self.fb_msg, True, self.fb_col), (box.x + 20, box.y + 50))
game = PointingGame()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit(); sys.exit()
elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
game.handle_click(event.pos)
game.draw()
pygame.display.flip()
CLOCK.tick(60)
September 28, 2026
Pointing game with npc quests
The game engine generates a random quests like "click on top" or "click on obstacle". The human user has to follow the instruction to get a reward.
Labels:
Grounding problem
Subscribe to:
Post Comments (Atom)

No comments:
Post a Comment