This commit is contained in:
2025-03-12 15:35:25 -04:00
parent c9c03e09d7
commit 4e7a818801
10 changed files with 408 additions and 0 deletions
BIN
View File
Binary file not shown.
Binary file not shown.
+15
View File
@@ -0,0 +1,15 @@
import math
import ztime
class Action:
def __init__(self, msg, start_time, end_time):
self.msg = msg
self.start_time = start_time # Time object
self.end_time = end_time # Time object
def is_running(self, cur_time):
return cur_time < self.end_time
def is_done(self, cur_time):
return cur_time >= self.end_time
def get_msg(self):
return self.msg
+35
View File
@@ -0,0 +1,35 @@
import action
class Agent:
def __init__(self, name, stats,
idle_message="Idle",
action=None):
self.name = name
self.stats = stats
self.idle_message = idle_message
self.action = action
def get_stat(self, stat_name):
return self.stats[stat_name]
def change_stat(self, stat_name, amt):
stat = self.stats[stat_name]
stat.change_index(amt)
def get_name(self):
return self.name
def get_action(self):
return self.action
def set_action(self, action):
self.action = action
def update_action(self, cur_time):
if self.action is not None:
if self.action.is_done(cur_time):
self.action = None
def is_idle(self):
return self.action is None
def get_idle_message(self):
return self.idle_message
def get_action_message(self):
if self.is_idle():
return self.idle_message
else:
return self.action.get_msg()
+17
View File
@@ -0,0 +1,17 @@
class Stat:
def __init__(self, name, values, index=0):
self.name = name
self.values = values
self.index = index
def get_value(self):
return self.values[self.index]
def set_index(self, i):
self.index = i
if self.index < 0:
self.index = (self.index+len(self.values))%len(self.values)
if self.index >= len(self.values):
self.index = self.index%len(self.values)
def change_index(self, delta):
new_index = self.index+delta
self.set_index(new_index)
+11
View File
@@ -0,0 +1,11 @@
import enum
import ztime
import action
from defs import STATS
def tick_decisionsys(myagent, curtime):
pass
def make_decisionsys(myagent):
pass
+49
View File
@@ -0,0 +1,49 @@
import math
# List of tuples
# 0: Name of the speed
# 1: Milliseconds between ticks of the clock
# 2: How many minutes pass with each tick
GAME_SPEEDS = [
('paused',math.inf,0),
('very slow', 1000, 1),
('slow', 100, 1),
('normal',10, 1),
('fast',1, 4),
('very fast', 1, 8)]
# Background and text color
BG_COLOR = "lightblue1"
FG_COLOR = "black"
# You should modify this list of agent stats
# keys must be strings
# values should be lists
# The stats below are just examples to give you
# some inspiration. Come up with your own set
# based on the theme/setting you imagine.
STATS = {
'location':['home','work','daycare','bar','park','jail'],
'hungry':list(range(0,20)),
'tired':list(range(0,5)),
'bored':list(range(0,2)),
'purpose':list(range(0,3)),
'lonely':list(range(0,20)),
'money':list(range(0,1000)),
'dirty':list(range(0,5)),
'sad':list(range(0,10)),
'crazy':list(range(0,10)),
'frustrated':list(range(0,10)),
'lazy':list(range(0,10)),
'confident':list(range(0,10)),
'accomplished':list(range(0,10))
}
# Probably don't change this line.
STAT_NAMES = list(STATS.keys())
# Change if you want. I hope I don't get
# 40 submissions all about an agent named, Jimbo.
AGENT_NAME = 'Jimbo'
START_TIME = 1800 # 6:00 AM Monday
+244
View File
@@ -0,0 +1,244 @@
import pygame
import pygame.freetype
import math
import random
import agent_stat
import ztime
import action
import agent
import decision
from defs import *
# ###############################################################
class Display:
def __init__(self, screen, clock):
self.screen = screen
self.clock = clock
self.run = True
self.delta = 0
self.font = None
def draw_gobj(self, gobj):
pygame.draw.circle(
self.screen,
gobj.color,
gobj.pos(),
gobj.radius)
def draw_text(self, msg, x, y, color):
surface, rect = self.font.render(msg, color)
self.screen.blit(surface, (x, y))
def draw_line(self, p1, p2, color,width=1):
pygame.draw.line(
self.screen,
color,
p1,
p2,
width)
def init_display(sw, sh):
pygame.init()
screen = pygame.display.set_mode((sw,sh))
clock = pygame.time.Clock()
display = Display(screen, clock)
display.font = pygame.freetype.Font('JuliaMono-Bold.ttf', 18)
pygame.key.set_repeat(200,100)
return display
def wrap_text(text, font, width):
splt_text = text.split()
lines = []
cur = 0
line = ""
while cur < len(splt_text):
new_line = ""
if len(line) > 0:
new_line = f"{line} {splt_text[cur]}"
else:
new_line = splt_text[cur]
r = pygame.freetype.Font.get_rect(font, new_line)
if r.width > width:
lines.append(line)
line = ""
else:
line = new_line
cur += 1
if len(line) > 0:
lines.append(line)
return lines
# #################################################################
def MakeStats():
stats = {}
for n,vals in STATS.items():
astat = agent_stat.Stat(n,vals)
stats[n] = astat
return stats
def MakeAgent(agent_name, cur_time):
a = agent.Agent(
agent_name,
MakeStats(),
f"{agent_name} is doin' nuthin'."
)
return a
def UpdateAgent(myagent, curtime):
myagent.update_action(curtime)
def DrawUI(display,
cur_time,
myagent,
winw, winh,
stat_index,
game_speed,
decision_sys_running):
display.draw_text(
f"Day: {cur_time.day_of_week()}",
10,10,FG_COLOR)
display.draw_text(
f"Hour: {cur_time.hour():02}",
180,10,FG_COLOR)
display.draw_text(
f"Min: {cur_time.minit():02}",
300,10,FG_COLOR)
display.draw_text(
f"{myagent.get_name()}'s stats",
10,40,FG_COLOR)
display.draw_text(
f"Game: {game_speed[0]}",
410,10,FG_COLOR)
display.draw_text(
f"Decision Sys: {decision_sys_running}",
580,10,FG_COLOR)
display.draw_line((400,0),(400,winh),"black",2)
display.draw_text(
f"{myagent.get_name()}'s Action",
410,40,FG_COLOR)
wrapped_msg = wrap_text(myagent.get_action_message(),
display.font, 380)
y = 70
for msg in wrapped_msg:
display.draw_text(
msg,
410, y, FG_COLOR)
y += 25
y = 70
x = 10
for i,name in enumerate(STAT_NAMES):
s = myagent.get_stat(name)
c = FG_COLOR
if i == stat_index:
c = 'red'
display.draw_text(
f"{name:<12} {s.get_value()}",
x,y,c)
y += 25
if y+25 > winh:
x += 200
y = 70
def MakeDecisionSys(myagent):
decision.make_decisionsys(myagent)
def CheckDecisionSys(myagent, curtime):
decision.tick_decisionsys(myagent, curtime)
def GameLoop(display, _agent, _time):
winw, winh = pygame.display.get_window_size()
curtime = _time
myagent = _agent
stat_index = 0
old_speed = 0
sim_speed = 0
time_last_tick = 0
next_behavior_update = curtime
decision_sys_running = False
# Here is where the behavior is created before the
# game loop starts.
MakeDecisionSys(myagent)
while display.run:
ticks = display.clock.tick(60)
dt = ticks / 1000
for event in pygame.event.get():
if event.type == pygame.QUIT:
display.run = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
myagent.change_stat(STAT_NAMES[stat_index],-1)
elif event.key == pygame.K_RIGHT:
myagent.change_stat(STAT_NAMES[stat_index],1)
elif event.key == pygame.K_UP:
stat_index = ((stat_index-1)+len(STAT_NAMES))%len(STAT_NAMES)
elif event.key == pygame.K_DOWN:
stat_index = (stat_index+1)%len(STAT_NAMES)
elif event.key == pygame.K_LEFTBRACKET:
if sim_speed > 0:
sim_speed -= 1
elif event.key == pygame.K_RIGHTBRACKET:
if sim_speed < len(GAME_SPEEDS)-1:
sim_speed += 1
elif event.key == pygame.K_p:
if sim_speed == 0:
sim_speed = old_speed
else:
old_speed = sim_speed
sim_speed = 0
elif event.key == pygame.K_q:
display.run = False
elif event.key == pygame.K_d:
curtime.tick(60*24)
elif event.key == pygame.K_s:
curtime.tick(-60*24)
elif event.key == pygame.K_h:
curtime.tick(60)
elif event.key == pygame.K_g:
curtime.tick(-60)
elif event.key == pygame.K_m:
curtime.tick(1)
elif event.key == pygame.K_n:
curtime.tick(-1)
elif event.key == pygame.K_SPACE:
decision_sys_running = not decision_sys_running
# This function call checks the agent's action. If the
# action has expired, the agent is set to idle.
UpdateAgent(myagent, curtime)
# Here is where the agent's behavior is checked.
# and if necessary, is switched to another action.
if decision_sys_running:
CheckDecisionSys(myagent, curtime)
display.screen.fill(BG_COLOR)
DrawUI(display, curtime, myagent, winw, winh, stat_index,
GAME_SPEEDS[sim_speed], decision_sys_running)
pygame.display.flip()
if GAME_SPEEDS[sim_speed][1] - time_last_tick <= 0:
curtime.tick(GAME_SPEEDS[sim_speed][2])
time_last_tick = 0
else:
time_last_tick += ticks
def main():
display = init_display(800,600)
myagent = MakeAgent(AGENT_NAME, START_TIME)
cur_time = ztime.Time(START_TIME)
GameLoop(display, myagent, cur_time)
if __name__ == "__main__":
main()
BIN
View File
Binary file not shown.
+37
View File
@@ -0,0 +1,37 @@
import math
class Time:
MINS_IN_HOUR = 60
HOURS_IN_DAY = 24
DAYS_IN_WEEK = 7
DAYS_OF_WEEK = [
'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
'Friday', 'Saturday']
def __init__(self, minute):
self.minute = minute
def __lt__(self, o):
return self.minute < o.minute
def __eq__(self, o):
return self.minute == o.minute
def __ge__(self, o):
return self.minute >= o.minute
def __add__(self, o):
return Time(self.minute + o.minute)
def __str__(self):
return f"{self.day_of_week()} {self.hour():02}:{self.minit():02}"
def minit(self):
_min = self.minute % self.MINS_IN_HOUR
return _min
def hour(self):
hour = (self.minute // self.MINS_IN_HOUR) % self.HOURS_IN_DAY
return hour
def day(self):
day = (self.minute // (self.MINS_IN_HOUR*self.HOURS_IN_DAY)) % self.DAYS_IN_WEEK
return day
def day_of_week(self):
return self.DAYS_OF_WEEK[self.day()]
def tick(self, amt):
self.minute += amt
def infinity():
return Time(math.inf)