b3a05ac4 by Barry

partial combat system and bug fixes for go.. again?

1 parent 955331a5
......@@ -2,3 +2,60 @@
This project is a simple mud that runs entirely within an ESP8266 and can be accessed via the wifi portal it connects to.
## Next Steps
1. every tick loop through the players
2. for each player load the roomname_monsters.txt
3. execute any current action [flee (maybe later), attack, continue combat, special attack (if enough mp or stamina)]
4. Write results of action to the roomname_monsters.txt if the monster is killed or mp / stamina has changed. - Sidenote.. don't store inventory, get a list of possible inventory and randomize on death and drop on the ground (no corpses)
5. Process any special commands from the player [spells, special attacks based on stamina]
6. Write results of action to the player file [damage, mp use, stamina use]
7. Write any new inventory to the room file. Expire any inventory that is old TBD....
8. Every minute respawn mobs for any room the players are in.
## Mob Format
Mobs folder:
monstername.json
Example:
```
{
"name": "cricket",
"desc": "A small green chirping insect with large legs suited for jumping.",
"aa": "1d2",
"spawn": {
"hp": "2d2",
"mp": "0",
"sta": "10",
},
"say": [
"A cricket quietly chirps",
"A cricket moves quietly"
],
"sp": [],
"at": [
{"name": "kick", "cost":5, "dmg": "2d4", "desc": "The cricket kicks with powerful legs"},
{"name": "antenna tickle", "cost":2, "dmg": "1d3" "desc": "The cricket brushes you with antenna"},
]
}
```
All damage rolls are described in the number of times to roll and the random amount in dice format: 1d20 = 1 to 20, 2d6 = 2 to 12
* name - The name that will be displayed to the user when the monster is described
* desc - The description that will be displayed to the user when the monster is looked at
* aa - Auto-Attack amount that will be applied for every tick
* spawn - The values used when the spawner creates the monster to seed the values. A direct integer means the value will be set to that value always.
* hp - the starting hp range
* mp - the starting mp range
* sta - the stamina used to perform special attacks or actions
* say - Things when not in combat the monster will express to anyone in the room.
* sp - A list of spells that appear in the spells/ folder
* at - Special attacks
* name - The special attack name
* cost - The cost in stamina of the attack
* dmg - the amount of damage caused by this attack
* desc - the description to display when the attack is performed
......
......@@ -36,10 +36,14 @@ class CommandHandler(object):
if cmd in utils.load_object_from_file('rooms/' + players[id]["room"] + '.txt').get('exits'):
params = cmd + " " + params.lower().strip()
cmd = "go"
if cmd == '':
return True
ldict = locals()
with open('commands/{}.txt'.format(cmd), 'r', encoding='utf-8') as f:
exec(f.read(), globals(), ldict)
if ldict['next_command'] != None:
locals()['tokens'] = []
tokens = []
with open('commands/{}.txt'.format(ldict['next_command']), 'r', encoding='utf-8') as f:
exec(f.read())
return True
......
def go(id, params, players, mud, tokens):
def go(id, params, players, mud, tokens, command):
# store the exit name
params = params.lower().strip()
params = params.strip()
if params == '':
params = command
room_data = utils.load_object_from_file('rooms/' + players[id]["room"] + '.txt')
exits = room_data['exits']
# if the specified exit is found in the room's exits list
if params in exits:
# go through all the players in the game
for pid, pl in players.items():
......@@ -47,4 +50,4 @@ def go(id, params, players, mud, tokens):
else:
# send back an 'unknown exit' message
mud.send_message(id, "Unknown exit '{}'".format(params))
next_command = go(id, params, players, mud, tokens)
\ No newline at end of file
next_command = go(id, params, players, mud, tokens, cmd)
\ No newline at end of file
......
......@@ -49,21 +49,43 @@ def prompt(pid):
players[pid]["hp"] = 100
if 'mp' not in players[pid]:
players[pid]["mp"] = 100
if 'sta' not in players[pid]:
players[pid]["sta"] = 10
prompt = players[pid]["prompt"].replace('%hp', str(players[pid]["hp"])).replace('%mp', str(players[pid]["mp"]))
mud.send_message(pid, "\r\n" + prompt, '')
tick = 0.0
spawn = 0.0
# main game loop. We loop forever (i.e. until the program is terminated)
while True:
if 'esp' in sys.platform:
gc.collect()
print(flash_button.value())
if flash_button.value() == 0:
break
# pause for 1/5 of a second on each loop, so that we don't constantly
# use 100% CPU time
time.sleep(0.001)
tick += 0.001
if spawn >= 60:
spawn = 0
try:
ldict = {}
with open('spawner.txt', 'r', encoding='utf-8') as f:
exec(f.read(), globals(), ldict)
except Exception as e:
print('spawner error:')
print(e)
if tick >= 3:
spawn += tick
tick = 0
try:
ldict = {}
with open('mobs.txt', 'r', encoding='utf-8') as f:
exec(f.read(), globals(), ldict)
except Exception as e:
print('mob error:')
print(e)
# 'update' must be called in the loop to keep the game running and give
# us up-to-date information
mud.update()
......@@ -84,6 +106,7 @@ while True:
"aliases": {},
"hp": 100,
"mp": 100,
"sta": 10,
}
with open('welcome.txt', 'r', encoding='utf-8') as f:
for line in f:
......@@ -167,4 +190,5 @@ while True:
# Start WIFI Setup
if 'esp' in sys.platform:
if flash_button.value() == 0:
import wifiweb
\ No newline at end of file
print('Starting WIFIWeb')
import wifiweb
......
# 1. every tick loop through the players
# 2. for each player load the roomname_monsters.txt
# 3. execute any current action [flee (maybe later), attack, continue combat, special attack (if enough mp or stamina)]
# 4. Write results of action to the roomname_monsters.txt if the monster is killed or mp / stamina has changed. - Sidenote.. don't store inventory, get a list of possible inventory and randomize on death and drop on the ground (no corpses)
# 5. Process any special commands from the player [spells, special attacks based on stamina]
# 6. Write results of action to the player file [damage, mp use, stamina use]
# 7. Write any new inventory to the room file. Expire any inventory that is old TBD....
# 8. Every minute respawn mobs for any room the players are in.
# def randint(start, stop):
# return randrange(start, stop + 1)
def run_mobs(players, mud):
def randrange(start, stop=None):
if 'esp' in sys.platform:
if stop is None:
stop = start
start = 0
upper = stop - start
bits = 0
pwr2 = 1
while upper > pwr2:
pwr2 <<= 1
bits += 1
while True:
from urandom import getrandbits
r = getrandbits(bits)
if r < upper:
break
return r + start
else:
import random
return random.randrange(start)
for pid, player in players.items():
if not player['name']:
continue
print(player)
print('checking actions in room: ' + player['room'])
room_monsters = utils.load_object_from_file('rooms/{}_monsters.json'.format(player['room']))
for mon_name, monster in room_monsters.items():
print(mon_name)
monster_template = utils.load_object_from_file('mobs/{}.json'.format(mon_name))
print(monster)
for active_monster in monster['active']:
if active_monster['action'] == "attack":
if active_monster['hp'] == 0:
DEAD = 1
if "d" in monster_template['aa']:
dice = monster_template['aa'].split('d')
att = 0
for d in range(int(dice[0])):
att += randrange(int(dice[1]) + 1)
players[pid]['hp'] -= att
mud.send_message(pid, "You were hit by a %s for %d" % (mon_name, att,))
else:
print(randrange(120))
# {
# "cricket": {
# "max": 1,
# "active": [
# {
# "hp": 100,
# "mp": 0,
# "sta": 10,
# "action": "attack",
# "target": "test",
# }
# ]
# }
# }
#prompt(pid)
# active_mobs = utils.load_object_from_file('activemobs.json')
# # check to see if everything has been spawned that needs to be.
# {
# "cricket": {
# "room001": {
# "max": 2,
# "active": [
# {
# "hp": 100,
# "mp": 0,
# "sta": 10,
# "inv": []
# },
# {
# "hp": 100,
# "mp": 0,
# "sta": 10,
# "inv": []
# }
# ]
# },
# "tavern": {
# "max": 1,
# "active": [
# {
# "hp": 100,
# "mp": 0,
# "sta": 10,
# "inv": []
# }
# ]
# }
# }
# }
# for mob in active_mobs:
run_mobs(players, mud)
\ No newline at end of file
{
"name": "cricket",
"desc": "A small green chirping insect with large legs suited for jumping.",
"aa": "1d2",
"spawn": {
"hp": "2d2",
"mp": "0",
"sta": "10"
},
"say": [
"A cricket quietly chirps",
"A cricket moves quietly"
],
"sp": [],
"at": [
{"name": "kick", "cost":5, "dmg": "2d4", "desc": "The cricket kicks with powerful legs"},
{"name": "antenna tickle", "cost":2, "dmg": "1d3", "desc": "The cricket brushes you with antenna"}
]
}
\ No newline at end of file
{"name": "test", "room": "Tavern", "inventory": {"candle": 1}, "prompt": "%hp> ", "aliases": {}, "hp": 100, "mp": 100}
\ No newline at end of file
{"name": "test", "room": "Outside", "inventory": {"candle": 1}, "prompt": "%hp> ", "aliases": {}, "hp": 96, "mp": 100, "sta": 10}
\ No newline at end of file
......
......@@ -28,5 +28,5 @@ with open('releasepw.conf', 'r', encoding='utf-8') as f:
password = f.read()
for file in files:
os.system("python webrepl\webrepl_cli.py -p {} {} 192.168.1.126:/{}".format(password, file, file))
os.system("python webrepl\webrepl_cli.py -p {} {} 192.168.1.189:/{}".format(password, file, file))
......
{
"title": "Outside the Tavern",
"description": "You are standing outside of a simple tavern made of pressed clay and shale roof. The door becons you to come in and have a drink.",
"exits": {"tavern": "Tavern"},
"look_items": {
"tavern": "A roughly constructed building."
},
"inventory": {}
}
\ No newline at end of file
{"title": "Outside the Tavern", "description": "You are standing outside of a simple tavern made of pressed clay and shale roof. The door becons you to come in and have a drink.", "exits": {"tavern": "Tavern"}, "look_items": {"tavern": "A roughly constructed building."}, "inventory": {"candle": 1}}
\ No newline at end of file
......
{
"cricket": {
"max": 1,
"active": [
{
"hp": 100,
"mp": 0,
"sta": 10,
"action": "attack",
"target": "test"
}
]
}
}
\ No newline at end of file
def spawn_mobs(players):
for pid, player in players.items():
print('checking spawn in room: ' + player['room'])
spawn_mobs(players)
\ No newline at end of file