Commits

Patrick Dawson  committed 5234afe

.

  • Participants
  • Parent commits 806bb44

Comments (0)

Files changed (4)

File data/die1.wav

Binary file added.

File data/die2.wav

Binary file added.
 
 TRAIN = 'TRAIN'
 
-from random import randint, shuffle
+from random import randint, shuffle, choice
 from common import *
 
 def roll(num, sides, mod=0):
     
 class Character(object):
     def __init__(self):
+        self.name = "Blue Dragon"
         self.img = None
         self.pos = None
-        self.hp = 1
-        self.ac = 11 # no armor
-        self.dmg = (1,4)
-        self.ab = 0
+        self.enemy = False
+        self.hp = 100
+        self.ac = 20
+        self.dmg = (6,8)
+        self.ab = 8
         self.str = 0
         self.dex = 0
+        
+    def __str__(self):
+        return self.name
 
 class Militia(Character):
     def __init__(self):
+        Character.__init__(self)
+        self.name = "Militia"
         self.img = IL("militia")
         self.hp = 6 # level 1 fighter
         self.ac = 13 # leather
         
 class Infantry(Character):
     def __init__(self):
+        Character.__init__(self)
+        self.name = "Infantry"
         self.img = IL("infantry")
         self.hp = 12 # level 2 fighter
         self.ac = 16 # chainmail + shield
         
 class Archer(Character):
     def __init__(self):
+        Character.__init__(self)
+        self.name = "Archer"
         self.img = IL("archer")
         self.hp = 6
         self.ac = 13
 class EnemyMilitia(Militia):
     def __init__(self):
         Militia.__init__(self)
+        self.name = "Enemy Scout"
         self.img = IL("enemy_militia")
+        self.enemy = True
 
 class EnemyInfantry(Militia):
     def __init__(self):
         Infantry.__init__(self)
+        self.name = "Enemy Infantry"
         self.img = IL("enemy_infantry")
+        self.enemy = True
 
 class EnemyArcher(Militia):
     def __init__(self):
         Archer.__init__(self)
+        self.name = "Enemy Archer"
         self.img = IL("enemy_archer")
+        self.enemy = True
 
 
 class WoodWalls(object):
 class GameEvents(object):
     attack = {
         2 : [(EnemyMilitia,2)],
+        8 : [(EnemyMilitia,2),(EnemyArcher,2)],
+        12 : [(EnemyMilitia,2),(EnemyArcher,2),(EnemyInfantry,2)],
+        19 : [(EnemyMilitia,0),(EnemyArcher,4),(EnemyInfantry,6)],
     }
+    win_turn = 21
 
 class Fort(object):
     def __init__(self):
             (BUILD,FARM) : (WOOD,15),
             (BUILD,BARRACKS) : (WOOD,20),
             (BUILD,WALLS) : (WOOD,50),
-            (TRAIN,MILITIA) : (FOOD,5),
+            (TRAIN,MILITIA) : (FOOD,10),
             (TRAIN,INFANTRY) : (FOOD,25),
             (TRAIN,ARCHER) : (FOOD,20),
             (TRAIN,WORKER) : (FOOD,30),
         }
         self.tasks = []
         self.turn = 1
-        self.battle = False
+        self.battle = Battle(None)
         self.buildings = []
         self.free_plots = 6
         self.free_barracks = 0
         self.walls = None
-        self.observers = []
+        self.fort_observers = None
+        self.battle_observers = None
         self.defenders = []
         self.attackers = []
         self.reset_tasks()
             return False
         if (task,arg) in self.cost:
             rtype,rnum = self.cost[(task,arg)]
-            print rtype, rnum
             if self.res[rtype] < rnum:
                 return False
         if task == TRAIN and arg != WORKER:
         return True
         
     def assign(self, task, arg=None):
-        print len(self.tasks)
         if not self.task_possible(task,arg):
             return False
 
             rtype,rnum = self.cost[(task,arg)]
             self.res[rtype] -= rnum
                 
-        print 'add task:', task, arg
         self.tasks.append((task,arg))
         return True
         
         for b in self.buildings:
             b.turn()
         for task,arg in self.tasks:
-            print task,arg
             if task in [CHOP_WOOD,HUNT]:
                 rtype,rnum = self.gather[task]
                 self.res[rtype] += rnum
 
         if self.turn in GameEvents.attack:
             self.start_battle(GameEvents.attack[self.turn])
+        elif self.turn == GameEvents.win_turn:
+            for o in self.fort_observers:
+                o.fort_win()
             
     def start_battle(self, enemy_force):
-        self.defenders = []
-        self.attackers = []
+        self.battle = Battle(self.battle_observer)
         for etype, enum in enemy_force:
             for n in range(enum):
-                self.attackers.append(etype())
+                self.battle.attackers.append(etype())
         for ptype, pnum in self.pop.items():
             for n in range(pnum):
                 if ptype == MILITIA:
-                    self.defenders.append(Militia())
+                    self.battle.defenders.append(Militia())
                 elif ptype == INFANTRY:
-                    self.defenders.append(Infantry())
+                    self.battle.defenders.append(Infantry())
                 elif ptype == ARCHER:
-                    self.defenders.append(Archer())
-        self.battle = True
-        for o in self.observers:
-            o.battle_start()
+                    self.battle.defenders.append(Archer())
+
+        self.fort_observer.fort_start_battle()
+        self.battle_observer.battle_start()
         
     def battle_observe(self, o):
-        self.observers.append(o)
+        self.battle_observer = o
+        
+    def fort_observe(self, o):
+        self.fort_observer = o
 
 
 class Battle(object):
-    def __init__(self):
+    def __init__(self, obs):
         self.defenders = []
-        self.enemies = []
+        self.attackers = []
         self.initiative = []
+        self.observer = obs
+        
+    def tick(self):
+        if len(self.initiative) == 0:
+            self._roll_initiative()
+            print self.initiative
+        src = self.initiative.pop()[0]
+        if src.hp > 0:
+            tgt = self._pick_target(src)
+            self.observer.battle_miss(src,tgt)
+            
+    def _pick_target(self, src):
+        opp = None
+        if src in self.defenders:
+            opp = self.attackers
+        else:
+            opp = self.defenders
+        return choice(opp)
         
     def _roll_initiative(self):
         ilist = []
-        for s in self.defenders, self.enemies:
+        for s in self.defenders, self.attackers:
             for ch in s:
                 r = roll(1,6)
                 amod = ch.dex
                 ilist.append((ch, ini))
         shuffle(ilist)
         self.initiative = sorted(ilist, key=lambda tup: tup[1], reverse=True)
-
+        
+    def _unit_attack(self, src, tgt):
+        # roll hit
+        # roll damage
+        pass
             IntroScreen : IntroScreen(self),
             FortScreen : FortScreen(self),
             BattleScreen : BattleScreen(self),
+            WinScreen : WinScreen(self),
+            LoseScreen : LoseScreen(self),
         }
         
     def change(self, new_screen):
         
     def clickContinue(self):
         self.sm.change(FortScreen)
+        
+        
+class LoseScreen(Screen):
+    def __init__(self, sm):
+        Screen.__init__(self, sm)
+        
+        mytxt = """
+        You have failed.
+        """
+        
+        self.txt = sgc.widgets.Label(text=mytxt, font=FC('Artifika-Regular', 16), pos=(200,200))
+        self.add(self.txt)
+
+class WinScreen(Screen):
+    def __init__(self, sm):
+        Screen.__init__(self, sm)
+        
+        mytxt = """
+        You have won.
+        """
+        
+        self.txt = sgc.widgets.Label(text=mytxt, font=FC('Artifika-Regular', 16), pos=(200,200))
+        self.add(self.txt)
 
 
 class BattleScreen(Screen):
         self.txt.addLine('Combat begins!')
         self.bf.draw_canvas()
         
+    def battle_hit(self, src, tgt, dmg):
+        self.txt.addLine('%s hits %s for %d' % (src,tgt,dmg))
+        if src.enemy:
+            AudioMixer.play('hit2')
+        else:
+            AudioMixer.play('hit1')
+        self.bf.hit(src,tgt,dmg)
+    
+    def battle_miss(self, src, tgt):
+        self.txt.addLine('%s misses!' % src)
+        if src.enemy:
+            AudioMixer.play('miss1')
+        else:
+            AudioMixer.play('miss2')
+        self.bf.miss(src,tgt)
+    
+    def battle_die(self, tgt):
+        pass
+    
+    def battle_won(self):
+        self.sm.change(FortScreen)
+    
+    def battle_lost(self):
+        self.sm.change(LoseScreen)
+        
     def update(self, dt):
         self.sm.surface.blit(self.bf.canvas, (64,8))
         self.t += dt
         if self.t >= 1000:
             self.t = 0
-            AudioMixer.play('hit1')
-            self.txt.addLine('tick')
+            FORT.battle.tick()
 
 
 class Battlefield(object):
                              (7,3),(7,5),(7,2),(7,6),(7,1),(7,7),(7,0),(7,8),(7,4)]
         self.draw_canvas()
         
+    def hit(self, src, tgt, dmg):
+        self.draw_canvas()
+        self.canvas.blit(IL("unit_yellow"), (src.pos[0]*64,src.pos[1]*64))
+        self.canvas.blit(IL("unit_red"), (tgt.pos[0]*64,tgt.pos[1]*64))
+        self.canvas.blit(ImageLoader.damage(dmg), (tgt.pos[0]*64,tgt.pos[1]*64))
+        
+    def miss(self, src, tgt):
+        self.draw_canvas()
+        self.canvas.blit(IL("unit_yellow"), (src.pos[0]*64,src.pos[1]*64))
+        self.canvas.blit(IL("unit_red"), (tgt.pos[0]*64,tgt.pos[1]*64))
+        
     def draw_canvas(self):
         self.canvas.fill((100,100,100))
         self.blit_grass()
     def blit_defenders(self):
         aslot = 0
         fslot = 0
-        for d in FORT.defenders:
+        for d in FORT.battle.defenders:
             pos = None
             if type(d) == Archer:
                 pos = self.archer_slots[aslot]
     
     def blit_attackers(self):
         eslot = 0
-        for e in FORT.attackers:
+        for e in FORT.battle.attackers:
             pos = self.enemy_slots[eslot]
             eslot += 1
             
         self.add(self.btn_next_turn)
         
         self.update_buttons()
+        FORT.fort_observe(self)
         
     def update_buttons(self):
         for btn, targs in self.task_map.items():
         else:
             self.btn_next_turn.disable()
             
-        self.txt_turn.config(text='TURN %d' % FORT.turn)
+        self.txt_turn.config(text='WEEK %d' % FORT.turn)
         self.txt_inst.config(text='Assign %d workers' % FORT.workers_available())
         
     def _doTask(self, task, arg=None):
         FORT.next_turn()
         self.rd.blit_resources()
         self.fs.draw_canvas()
-        self.update_buttons()
+        self.update_buttons()        
         
-        if FORT.battle:
-            self.sm.change(BattleScreen)
+    def fort_start_battle(self):
+        self.sm.change(BattleScreen)
+        
+    def fort_win(self):
+        self.sm.change(WinScreen)
+        
+    def fort_lose(self):
+        self.sm.change(LoseScreen)
         
     def update(self, dt):
         self.draw()